美文网首页
设计模式

设计模式

作者: 磨人的磨磨虫 | 来源:发表于2019-04-02 14:39 被阅读0次

    1.单例模式
    保证全局只有一个实例,节省资源,类似java的静态类 static,一般用到的地方有历史记录、线程池等等

    let Singleton=function(){
      this.name=1
    }
    //因为javascript 没有静态类的标识 故用闭包保持唯一性 外部无法访问instance
    Singleton.getInstance=(function(){
      let instance=null
      return function(){
        if(!instance ){
            instance=new Singleton()
        }
        return instance
      }
    })()
    
    let s1=Singleton.getInstance()
    let s2=Singleton.getInstance()
    console.log(s1===s2)//true
    console.log(s1.name)//1
    s1.name=2
    console.log(s1.name)//2
    console.log(s2.name)//2
    

    2.策略类
    比如算法,各种算法封装在策略类,各种方法的使用交给环境类
    看代码:

    
    let strategy={
      //冒泡排序 逐个调换位置
      A(numbers){
        for(let i=0;i<numbers.length;i++){
          for(let j=0;j<numbers.length;j++){
            let itemNext=numbers[j+1]
            let item=numbers[j]
            if(itemNext<item){
                numbers[j+1]=item
                numbers[j]=itemNext
            }
          }
        }
        return numbers
      },
      //选择排序 每次循环把最小的放入前置位
      B(numbers){
        for(let i=0;i<numbers.length;i++){
          let itemI=numbers[i]
          for(let j=i+1;j<numbers.length;j++){
            let itemJ=numbers[j]
            if(itemI>itemJ){
                numbers[i]=itemJ
                numbers[j]=itemI
                itemI=itemJ
            }
          }
        }
        return numbers
      }
    }
    let content=name=>{
      let numbers=[1,3,5,6,1,3,4,6,5]
      return strategy[name](numbers)
    }
    console.log(content('A'))
    console.log(content('B'))
    

    3.代理模式
    高度解耦,对象保护,易修改,因为是代理,所以会慢一点
    示例代码:

    let myImg={
      setSrc(img,src){
        img.src=src
      }
    }
    
    let proxyImg={
      setImg(imgNode,src){
        //实现图片懒加载
        myImg.setSrc(imgNode,'默认图.png')//占位图片
        let img=new Image()
        imgNode.onLoad=function(){
          myImg.setSrc(imgNode,src)
        }
        img.src=src//真正要加载的产品图片
      }
    }
    let imgNode=document.crateElement('img')
    let imgUrl='产品图.png'
    document.body.append(imgUrl)
    
    proxyImg.setImg(imgNode,imgUrl)
    

    4.迭代器模式
    迭代器模式是指提供一种方法顺序访问一个集合对象的各个元素,使用者不需要了解集合对象的底层实现。
    不太清楚其用途~

    let Iterator=obj=>{
      let current=0;
      let next = ()=>current+=1
      let end = ()=>current>=obj.length
      let get = ()=>obj[current]
      return{
        next,
        end,
        get
      }
    }
    let myIter = Iterator([1, 2, 3]);
    while(!myIter.end()) { 
      console.log(myIter.get()) myIter.next(); 
    }
    

    5.订阅发布模式
    订阅-发布模式定义了对象之间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都可以得到通知。

    event.js
    class Event{
      constructor(){
        this._cbs={}
      }
      //订阅
      on(key,fn){
        if(typeof fn != "function"){
          return false
        }
        this._cbs = this._cbs || {};
        (this._cbs[key] = this._cbs[key] || []).push(fn)
      }
      //发布
      emit(){
         let _cbs=this._cbs
         let key=Array.prototype.shift.apply(arguments)
         let affair =_cbs[key]||[]
         if(!affair||affair.length<1){
          return false
         }
         for(let fn of affair){
           fn.apply(null,arguments)
         }
         return true
      }
      //销毁
      off(key,fn){
        this._cbs = this._cbs || {}
        // all
        if (!arguments.length) {
          this._cbs = {}
          return true
        }
        var callbacks = this._cbs[key]
        if (!callbacks) return
        // remove all handlers
        if (arguments.length === 1) {
          delete this._cbs[key]
          return true
        }
     // remove specific handler
        var cb
        for (var i = 0, len = callbacks.length; i < len; i++) {
          cb = callbacks[i]
          if (cb === fn || cb.fn === fn) {
            callbacks.splice(i, 1)
            break
          }
        }
        return true
      }
    }
    
    export default Event
    
      //a.js
      import Event from event.js
      let e=new Event()
      e.on('one',v=>{
        console.log('订阅')
        console.log(v)
      })
    
       e.emit('one',1000)
       e.off('one')
       e.emit('one',1000)
    

    6.工厂模式
    工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。” 简单来说:就是把new对象的操作包裹一层,对外提供一个可以根据不同参数创建不同对象的函数。

    class Dog{
      run(){
          console.log('狗')
      }
    }
    
    class Cat{
      run(){
          console.log('猫')
      }
    }
    
    class Animal{
      constructor(name){
        name = name.toLocaleLowerCase()
        switch(name){
          case 'cat':
            return new Dog()
          case 'dog':
            return new Cat()
          default:
            console.log('没有哦')
        }
      }
    }
    
    let ss=new Animal('cat')
    ss.run()
    

    7.组合模式
    用小的子对象构造更大的父对象,而这些子对象也由更小的子对象构成 单个对象和组合对象对于用户暴露的接口具有一致性,而同种接口不同表现形式亦体现了多态性

    // 文件类
    class File {
      constructor(name) {
        this.name = name || "File";
      }
    
      add() {
        throw new Error("文件夹下面不能添加文件");
      }
    
      scan() {
        console.log("扫描文件: " + this.name);
      }
    }
    
    // 文件夹类
    class Folder {
      constructor(name) {
        this.name = name || "Folder";
        this.files = [];
      }
    
      add(file) {
        this.files.push(file);
      }
    
      scan() {
        console.log("扫描文件夹: " + this.name);
        for (let file of this.files) {
          file.scan();
        }
      }
    }
    
    let home = new Folder("用户根目录");
    
    let folder1 = new Folder("第一个文件夹"),
      folder2 = new Folder("第二个文件夹");
    
    let file1 = new File("1号文件"),
      file2 = new File("2号文件"),
      file3 = new File("3号文件");
    
    // 将文件添加到对应文件夹中
    folder1.add(file1);
    
    folder2.add(file2);
    folder2.add(file3);
    
    // 将文件夹添加到更高级的目录文件夹中
    home.add(folder1);
    home.add(folder2);
    
    // 扫描目录文件夹
    home.scan();
    
    

    8.享元模式
    享元模式:运用共享技术来减少创建对象的数量,从而减少内存占用、提高性能。

    class ObjectPool{
      constructor(){
        this._pool=[]
      }
      create(obj){
        return this._pool.length===0?
        new obj(this):
        this._pool.shift()
      }
      recover(obj){
        return this._pool.push(obj);
      }
      // 对象池大小 
      size() { 
        return this._pool.length; 
      }
    }
    
    // 模拟文件对象
    class File {
      constructor(pool) {
        this.pool = pool;
      }
    
      // 模拟下载操作
      download() {
        console.log(`+ 从 ${this.src} 开始下载 ${this.name}`);
        setTimeout(() => {
          console.log(`- ${this.name} 下载完毕`); // 下载完毕后, 将对象重新放入对象池
          this.pool.recover(this);
        }, 100);
      }
    }
    
    /****************** 以下是测试函数 **********************/
    
    let objPool = new ObjectPool();
    
    let file1 = objPool.create(File);
    file1.name = "文件1";
    file1.src = "https://download1.com";
    file1.download();
    
    let file2 = objPool.create(File);
    file2.name = "文件2";
    file2.src = "https://download2.com";
    file2.download();
    
    setTimeout(() => {
      let file3 = objPool.create(File);
      file3.name = "文件3";
      file3.src = "https://download3.com";
      file3.download();
    }, 200);
    
    setTimeout(
      () =>
        console.log(
          `${"*".repeat(50)}\n下载了3个文件,但其实只创建了${objPool.size()}个对象`
        ),
      1000
    );
    

    相关文章

      网友评论

          本文标题:设计模式

          本文链接:https://www.haomeiwen.com/subject/jkhwbqtx.html