
代理模式
要解決的問題
代理模式主要解決的問題是將復雜的操作邏輯隱藏起來,讓方法的使用者只使用幾個固定的set和get類方法就可以簡單的實現(xiàn)一些功能。而且代碼還不失擴展性和維護性。
能解決的常見問題
-
圖片預加載
一般網(wǎng)頁上顯示圖片如果直接img標簽中寫上src,在用戶訪問網(wǎng)頁時可能因為網(wǎng)速的原因,會顯示一大片空白的區(qū)域,這樣容易引起不明真相的用戶的困惑。所以目前一般的網(wǎng)站都會有圖片預加載機制,也就是在真正的圖片在被加載完成之前用一張菊花圖(轉(zhuǎn)圈的gif圖片)表示正在加載圖片。
<div>
<h3>這是一張圖片標題</h3>
</div>
TS代碼
/* 生成一張圖片 */
class myImg{
imgNode = document.createElement("img");
constructor(where:HTMLElement){
this.appendTo(where);
};
private appendTo(where:any){
where.appendChild(this.imgNode);
}
setSrc( src:string ){
this.imgNode.src = src;
}
}
/* 封裝一個類嗲用前一個類,等待網(wǎng)絡(luò)圖片加載完成之前先設(shè)置一張loading菊花圖,加載完成后將圖片換成該顯示的圖片 */
class PreloadImg extends myImg{
img = new Image;
constructor( where: HTMLElement){
super(where);
}
setSrc(src:string){
super.setSrc('loading.gif')
this.img.src = src;
this.img.onload = ()=>{
super.setSrc(src);
}
}
}
/*循環(huán)調(diào)用前一個類,插入圖片的顯示列表*/
class LoadImgList extends PreloadImg{
constructor(list:string[],place:HTMLElement){
super(place);
list.map((item)=>{
super.setSrc(item);
})
}
}
/* Test */
let place = document.getElementsByTagName('div')[0];
let list = [
"圖片鏈接1",
"圖片鏈接2",
"圖片鏈接3",
];
new LoadImgList(list,place); //插入顯示圖片列表
可以看出上面的代碼實現(xiàn)的兩層的代理,符合單一職責的原則
1.myImg類的作用是在指定的位置插入一張圖片,并有setSrc的方法用來為圖片設(shè)置路徑。
2.PreloadImg類繼承了myImg,作用是用來在加載圖片的過程中先顯示一張占位的loading菊花圖,而在圖片加載完畢后將占位菊花圖換成加載下來的圖片。
3.LoadImgList類繼承了PreloadImg類,作用是用來將圖片隊數(shù)組中的圖片鏈接自動的加載到圖片要插入的地方。
4.可以看出代理模式是將復雜的邏輯一步一步的封裝到每個類中,而且每個類都有自己唯一的職責。而用戶只要使用最后的LoadImgList類不用理會背后的邏輯就可以使用圖片預加載功能。同時代碼也具有可擴展性和相對好的可維護性。
- 緩存計算結(jié)果
/* 用到了 單例模式 和 代理模式:用代理模式實現(xiàn)單例模式實現(xiàn)計算的緩存*/
/*負責計算相乘的結(jié)果*/
class Mult{
protected getResult(...args){
console.log('開始計算');
return args.reduce((x,y)=>{
return x*y;
});
}
}
/*代理Mult類,緩存計算的內(nèi)容*/
class CacheMult extends Mult{
cache:object = {};
constructor(){
super();
}
getResult(...args){
let sorted_args = args.sort((n1,n2)=>n1-n2);
let key = sorted_args.join(",")
if ( key in this.cache ){ //如果結(jié)果已經(jīng)計算過了,就返回緩存過的結(jié)果
return this.cache[key];
}else{
let result = super.getResult(...args); //調(diào)用父類得到計算結(jié)果
this.cache[ key ] = result; //緩存結(jié)果到緩存中
return result;
}
}
}
let mult = new CacheMult();
let r1 = mult.getResult(1,2,3,4);
let r2 = mult.getResult(1,2,3,4);
let r3 = mult.getResult(1,2,3);
console.log(r1);
console.log(r2);
console.log(r3);
/* 運行結(jié)果 */
// 開始計算
// 開始計算
// 24
// 24
// 6
從上面的代碼中可以看出,CacheMult類代理了Mult類來事項緩存計算結(jié)果的功能,防止出現(xiàn)重復計算,這樣可以再某一些計算密集型的場景下有效的節(jié)省計算資源,提高代碼的性能。