設(shè)計模式之代理模式

代理模式

要解決的問題

代理模式主要解決的問題是將復雜的操作邏輯隱藏起來,讓方法的使用者只使用幾個固定的setget類方法就可以簡單的實現(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é)省計算資源,提高代碼的性能。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 代理是一個對象,它可以用來控制對本體對象的訪問,它與本體對象實現(xiàn)了同樣的接口,代理對象會把所有的調(diào)用方法傳遞給本體...
    JSUED閱讀 362評論 0 0
  • 在某些情況下,一個客戶不想或者不能直接引用一個對象,此時可以通過一個稱之為“代理”的第三者來實現(xiàn) 間接引用。代理對...
    逆風飛行1226閱讀 502評論 0 2
  • 代理模式是為一個對象提供一個代用品或占位符,以便控制對它的訪問。 代理模式的關(guān)鍵是,當客戶不方便直接訪問一個對象或...
    風銘閱讀 1,616評論 0 0
  • 代理模式 在某些應(yīng)用中,我們想要在訪問某個對象之前執(zhí)行一個或多個重要的操作,例如,訪問敏感信息——在允許用戶訪問敏...
    英武閱讀 3,340評論 0 51
  • 已經(jīng)是情人節(jié)第二天了,和基友廝混3天2夜再不回家我媽怕是會拿棍子請我回家。。。狗糧不撒。只是想表達下,認識基友第7...
    最愛顛茄小F閱讀 310評論 0 0

友情鏈接更多精彩內(nèi)容