14-设计模式-外观模式(设计模式学习笔记)

外观模式

为一组复杂的子系统接口提供一个更高级的统一接口,通过这个接口使得对子系统接口的访问更容易。

外观模式本质

封装交互 简化调用

外观模式的核心思想

用户不需要关心里面是如何调用,如何使用的,我们只需要有一个能提供给我们实现功能的接口就行

外观模式的主要角色

image.png

1、外观(Facade)角色 :客户端可以调用这个角色的方法。此角色知晓相关子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。

2、子系统(SubSystem)角色 :可以同时有一个或者多个子系统。每个子系统都不是一个单独的类,而是一个类的集合。每个子系统都可以被客户端直接调用,或者被外观角色调用。子系统并不知道外观角色的存在,对于子系统而言,外观角色仅仅是另外一个客户端而已。

具体示例

一键完成多种操作

    // 例子1:一键完成 装弹,打蛋,换蛋 三个操作
    class A{
        a1(){} // 装弹
        a2(){} // 打蛋
        a3(){} // 换蛋

        a_init(){ // 一键操作
            this.a1() // 调用装弹
            this.a2() // 调用打蛋
            this.a3() // 调用换蛋
        }
    }

    let a = new A()

    // 没有使用外观模式就需要这么繁琐
    a.a1() // 装弹
    a.a2() // 打蛋
    a.a3() // 换蛋

    // 使用外观模式
    a.a_init() // 一键操作装弹打蛋换蛋
复制代码

浏览器事件监听函数的兼容

    // 例子2:浏览器兼容事件监听函数

    // 有的浏览器支持el.addEventListener(),而有的浏览器只支持el.attachEvent(),此时就需要用外观模式设计一个函数来兼容
    function addMyEvent(el,type,fn){ // 接收参数:元素,事件类型,回调函数
        if(浏览器支持addEventListener()){
            // 就使用el.addEventListener()
        }else{ // 否则就是支持attachEvent()
            // 就使用attachEvent()
        }
    }

    // 然后以后需要使用事件监听的时候,只需要执行该兼容函数即可
    addMyEvent(el,type,fn)
复制代码

模拟jq源码

    // 例子3:模拟jq源码
    var A = {
        get:function (id){
            return document.getElementById(id)
        },
        css:function (id,key,value){
            this.get(id).style[key] = value
        },
        html:function (id,content){
            this.get(id).innerHTML = content
        },
    }

    // 使用外观模式 直接打点调用封装好的方法 写的少
    A.html("box","这是新添加的内容1")
    A.html("box1","这是新添加的内容2")
    A.html("box2","这是新添加的内容3")
    A.html("box3","这是新添加的内容4")
    A.html("box4","这是新添加的内容5")
    A.html("box5","这是新添加的内容6")

    // 不使用外观模式 需要一条一条调用各种方法 很繁琐
    document.getElementById("box").innerHTML("这是新添加的内容1")
    document.getElementById("box1").innerHTML("这是新添加的内容2")
    document.getElementById("box2").innerHTML("这是新添加的内容3")
    document.getElementById("box3").innerHTML("这是新添加的内容4")
    document.getElementById("box4").innerHTML("这是新添加的内容5")
    document.getElementById("box5").innerHTML("这是新添加的内容6")

复制代码

模拟电脑开机过程

    // 例子4:模拟电脑开机
    // 不使用外观模式的电脑开机,每启动一个硬件就要调用一个方法
    function Cpu(){
        this.startUp = function (){
            console.log("Cpu启动")
        }
    }
    function Memory(){
        this.startUp = function (){
            console.log("Memory启动")
        }
    }
    function Disk(){
        this.startUp = function (){
            console.log("Disk启动")
        }
    }

    // 使用外观模式,一个按键即可调用所有硬件进行启动
    function Computer(){
        var _cpu,_memory,_disk
        _cpu = new Cpu()
        _memory = new Memory()
        _disk = new Disk()

        this.start = function (){
            _cpu.startUp() // cpu调用启动函数
            _memory.startUp() // memory调用启动函数
            _disk.startUp() // disk调用启动函数
        }
    }

    let c = new Computer() // 实例化对象
    c.start() // 对象直接打点调用方法就可一键操作电脑三个硬件启动
复制代码

外观模式优点

1、实现了子系统与客户端之间的松耦合关系。

2、客户端屏蔽了子系统组件,减少了客户端所需处理的对象数目,并使得子系统使用起来更加容易

外观模式适用场景

1、设计初期阶段,应该有意识的将不同层分离,层与层之间建立外观模式。

2、开发阶段,子系统越来越复杂,增加外观模式提供一个简单的调用接口。

3、维护一个大型遗留系统的时候,可能这个系统已经非常难以维护和扩展,但又包含非常重要的功能,为其开发一个外观类,以便新系统与其交互。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享