设计模式之代理模式

代理模式

要解决的问题

代理模式主要解决的问题是将复杂的操作逻辑隐藏起来,让方法的使用者只使用几个固定的setget类方法就可以简单的实现一些功能。而且代码还不失扩展性和维护性。

能解决的常见问题

  • 图片预加载
    一般网页上显示图片如果直接img标签中写上src,在用户访问网页时可能因为网速的原因,会显示一大片空白的区域,这样容易引起不明真相的用户的困惑。所以目前一般的网站都会有图片预加载机制,也就是在真正的图片在被加载完成之前用一张菊花图(转圈的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;
    }
}
/* 封装一个类嗲用前一个类,等待网络图片加载完成之前先设置一张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类来事项缓存计算结果的功能,防止出现重复计算,这样可以再某一些计算密集型的场景下有效的节省计算资源,提高代码的性能。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 代理是一个对象,它可以用来控制对本体对象的访问,它与本体对象实现了同样的接口,代理对象会把所有的调用方法传递给本体...
    JSUED阅读 304评论 0 0
  • 在某些情况下,一个客户不想或者不能直接引用一个对象,此时可以通过一个称之为“代理”的第三者来实现 间接引用。代理对...
    李序锴阅读 414评论 0 2
  • 代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。 代理模式的关键是,当客户不方便直接访问一个对象或...
    风铭阅读 1,564评论 0 0
  • 代理模式 在某些应用中,我们想要在访问某个对象之前执行一个或多个重要的操作,例如,访问敏感信息——在允许用户访问敏...
    英武阅读 3,225评论 0 51
  • 已经是情人节第二天了,和基友厮混3天2夜再不回家我妈怕是会拿棍子请我回家。。。狗粮不撒。只是想表达下,认识基友第7...
    最爱颠茄小F阅读 265评论 0 0