設計模式之代理模式

代理模式

要解決的問題

代理模式主要解決的問題是將複雜的操做邏輯隱藏起來,讓方法的使用者只使用幾個固定的setget類方法就能夠簡單的實現一些功能。並且代碼還不失擴展性和維護性。javascript

能解決的常見問題

  • 圖片預加載

通常網頁上顯示圖片若是直接img標籤中寫上src,在用戶訪問網頁時可能由於網速的緣由,會顯示一大片空白的區域,這樣容易引發不明真相的用戶的困惑。因此目前通常的網站都會有圖片預加載機制,也就是在真正的圖片在被加載完成以前用一張菊花圖(轉圈的gif圖片)表示正在加載圖片。html

<div>
    <h3>這是一張圖片標題</h3>
</div>

TS代碼java

/* 生成一張圖片 */
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;
    }
}
/* 封裝一個類嗲用前一個類,等待網絡圖片加載完成以前先設置一張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);
        }
    }
}

/*循環調用前一個類,插入圖片的顯示列表*/
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); //插入顯示圖片列表

能夠看出上面的代碼實現的兩層的代理,符合單一職責的原則
1.myImg類的做用是在指定的位置插入一張圖片,並有setSrc的方法用來爲圖片設置路徑。
2.PreloadImg類繼承了myImg,做用是用來在加載圖片的過程當中先顯示一張佔位的loading菊花圖,而在圖片加載完畢後將佔位菊花圖換成加載下來的圖片。
3.LoadImgList類繼承了PreloadImg類,做用是用來將圖片隊數組中的圖片連接自動的加載到圖片要插入的地方。
4.能夠看出代理模式是將複雜的邏輯一步一步的封裝到每一個類中,並且每一個類都有本身惟一的職責。而用戶只要使用最後的LoadImgList類不用理會背後的邏輯就可使用圖片預加載功能。同時代碼也具備可擴展性和相對好的可維護性。數組

  • 緩存計算結果
/* 用到了 單例模式 和 代理模式:用代理模式實現單例模式實現計算的緩存*/

/*負責計算相乘的結果*/
class Mult{
    protected getResult(...args){
        console.log('開始計算');
        return args.reduce((x,y)=>{
            return x*y;
        });
    }
}

/*代理Mult類,緩存計算的內容*/
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 ){  //若是結果已經計算過了,就返回緩存過的結果
            return this.cache[key];
        }else{
            let result = super.getResult(...args);  //調用父類獲得計算結果
            this.cache[ key ] = result; //緩存結果到緩存中
            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);
/* 運行結果 */
// 開始計算
// 開始計算
// 24
// 24
// 6

從上面的代碼中能夠看出,CacheMult類代理了Mult類來事項緩存計算結果的功能,防止出現重複計算,這樣能夠再某一些計算密集型的場景下有效的節省計算資源,提升代碼的性能。緩存

相關文章
相關標籤/搜索