设计者模式

痞子三分冷 提交于 2020-03-31 23:38:00

1. 单例模式:每个new出来的实例都需要有一个相同的方法,但是这时候如果 每个实例都新建一个这种方法,太占据内存也太慢,所以在这里有一个重要的判断:如果有实例,则返回实例;如果没有实例,则创建实例,并且返回实例。

例:

 
class CreateUser {
            static shareInstance(){
                if(!CreateUser.ins){
                    CreateUser.ins = new CreateUser('aa')
                }
                return CreateUser.ins;
            }
            constructor(name) {
                this.name = name;
                this.getName();
            }
            getName() {
                return this.name;
            }
 
        }
        let c1 = CreateUser.shareInstance()
        let c2 = CreateUser.shareInstance()
        console.log(c1==c2)

  

2. 组合模式:组合模式中基本对象和组合对象被一致对待;无须关心对象有多少层, 调用时只需在根部进行调用;类似DOM树

例:

const MacroCommand = function() {
  return {
    lists: [],
    add: function(task) {
      this.lists.push(task)
    },
    excute: function() { //  组合对象调用这里的 excute,
      for (let i = 0; i < this.lists.length; i++) {
        this.lists[i].excute()
      }
    },
  }
}


const command1 = MacroCommand() // 命令1
 
command1.add({
  excute: () => console.log('吃饭') // 
})
 
const command2 = MacroCommand() // 命令2
 
command2.add({
  excute: () => console.log('唱歌')
})
 
command2.add({
  excute: () => console.log('画画')
})
 
const command3 = MacroCommand() //命令3
 
command3.add({
  excute: () => console.log('下棋')
})
 
command3.add({
  excute: () => console.log('玩游戏')
})
 
const macroCommand = MacroCommand()//组合对象
macroCommand.add(command1)
macroCommand.add(command2)
macroCommand.add(command3)
 
macroCommand.excute()
 
// 吃饭
// 唱歌
//画画
// 下棋
// 玩游戏

  

3. 观察者模式:类似于事件监听, 观察者只要订阅了被观察者的事件,那么当被观察者的状态改变时,被观察者会主动去通知观察者,而无需关心观察者得到事件后要去做什么,实际程序中可能是执行订阅者的回调函数

例:

   var obj = {
            data: {
                list: []

            },
        }

        // defineProperty 可以观察 obj对象 的list 属性的使用
        Object.defineProperty(obj, 'list', {
            get() {
                console.log('获取了list 属性')
                console.log(this.data['list'])
                return this.data['list']
            },
            set(val) {
                console.log('值被更改了')

                this.data['list'] = val
            }
        })

        // 获取了list属性,那么get 方法就会被调用
        console.log(obj.list)
        // 设置了list属性set 方法就会被调用
        obj.list = ['a', 'b']

  

4. 工厂模式: 去做同样的事情,实现同样的效果,批量生产

例:

// 文本工厂
        class Text {
            constructor(text) {
                this.text = text
            }
            insert(where) {
                const txt = document.createTextNode(this.text)
                where.appendChild(txt)
            }
        }

        // 链接工厂
        class Link {
            constructor(url) {
                this.url = url
            }
            insert(where) {
                const link = document.createElement('a')
                link.href = this.url
                link.appendChild(document.createTextNode(this.url))
                where.appendChild(link)
            }
        }

  

5. 抽象的工厂模式:先标记好模式,然后下面引用,但是里面什么都没有

class DomFactory {

            constructor() {

            }


            // 各流水线

            insert() {


            }


        }

  

6. 策略模式:策略类部分和环境类部分

①策略类:写出好几种策略,类似于planA,planB….

例:

var levelOBJ = {
            "A": function (money) {
                return money * 4;
            },
            "B": function (money) {
                return money * 3;
            },
            "C": function (money) {
                return money * 2;
            }
        };
        /*环境类*/
        var calculateBouns = function (level, money) {
            return levelOBJ[level](money);
        };
        console.log(calculateBouns('A', 10000)); // 40000

②环境类:运行的环境

7. 代理模式:经典例子:刚打开页面的时候加载个loading图片占位,等图片加载过来后再显示该图片,提前占坑

例:

const MyImage = function (parent) {
            const imgNode = document.createElement('img')
            parent.appendChild(imgNode)

            // 提供一个方法 ,让外部也能修改 图片的src属性
            this.setSrc = function(src){
                imgNode.src = src
            }
            
        }
        // 直接添加图片 ,如果图片比较大,可能加载的比较慢,导致网页上的img一开始显示不出来
        let myImage   = new MyImage(document.body)

// 写个代理   提供 预加载功能
        const ProxyImage = function (myImage) {

            // 创建image对象
            const img = new Image()
            img.on
            // 监听img对象的 onload 方法
            img.onload = function () { // http 图片加载完毕后才会执行
                // 模拟网络很慢的情况
                setTimeout(()=>{
                    myImage.setSrc(this.src)

                },2000)
            }
            

            this.setSrc =function (src) {
                    // 加载时候先不加载大图,先加载一张小图(浏览器已经下载过的)
                    myImage.setSrc('loading.gif') // 本地 loading 图片
                    img.src = src
            }
        }
        //
        let proxyImage = new ProxyImage(myImage)
        proxyImage.setSrc('https://www.baidu.com/img/bd_logo1.png?where=super')

  

8. 适配器模式:类似于把obj对象转为数组,这时候如果是大量的操作怕出意外,就可以运用这种模式,就相当于有个中介转一下

例:

// 老接口
        const zhejiangCityOld = function () {
            return [{
                    name: 'hangzhou',
                    id: 11,
                },
                {
                    name: 'jinhua',
                    id: 12
                }
            ]
        }

        console.log(zhejiangCityOld())

        // 新接口希望是下面形式
        // {
        //     hangzhou: 11,
        //     jinhua:12
        // }

        // 这时候就可采用适配者模式
        const adaptor = function (oldCity) {
            console.log(oldCity)
            const obj = {}
            for (let city of oldCity) {
                obj[city.name] = city.id
            }
            return obj
        }


        let oldData = zhejiangCityOld();
        //把老数据放在适配器中产生新数据
        console.log(adaptor(oldData))

 

既然看了这么多设计者模式,接下来也可以了解一下hash,它在我们的应用中也很重要:

1.Hash:传统的网页根据用户访问的不同地址,浏览器从服务器获取对应页面的内容展示给用户,这样造成服务器压力比较大,用户访问比较慢,在这种场景下,出现了单页应用。

2. Hashchange:想要用hash就要监听到hash什么时候改变,这时候就需要用hashchange来监听

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!