专栏首页AlbertYang的编程之路设计模式(12)[JS版]--JavaScript必会设计模式之外观模式(Façade Pattern)

设计模式(12)[JS版]--JavaScript必会设计模式之外观模式(Façade Pattern)

1 什么是外观模式

外观模式为子系统提供了一个接口,它屏蔽一个或多个子系统的复杂功,提供了一个一致的界面(接口)给用户。外观模式是一个非常简单的模式,但它的功能却很很强大,非常有用。外观模式不仅简化类中的接口,而且对接口与调用者也进行了解耦。外观模式可以将一些复杂操作封装起来,并创建一个简单的接囗用于调用,它经常出现在多层架构的系统中。

外观模式的目的是提供一个高级接口(属性和方法),使子系统或工具箱更易于客户端使用。在多层网络应用中,经常有一个表现层,它是服务层的客户端。这两个层之间的通信是通过一个定义良好的API来实现的。这个API,或者说Façade,将复杂的业务对象和它们的交互隐藏在表现层之外。

另一个使用Façades的领域是在代码的重构中。假设你正在维护一个比较老的系统,里面有一些容易令人困惑或混乱的代码,而客户端不应该关注这些混乱的代码,你可以将这些代码隐藏在Façade后面,Façade只暴露出必要的东西,并呈现出一个更干净和易于使用的界面。外观模式经常与其他设计模式结合使用,外观模式本身经常用来实现单人工厂模式。

2 外观模式的主要的参与者

参与该模式的对象有

门面 (Facade ):

1 知道哪些子系统负责处理请求。

2 将客户的请求委托给相应的子系统对象。 子系统(Sub Systems) :

1 实现和执行专门的子系统功能。

2 对门面一无所知,也没有参照物。

3 代码实现

在下面的JavaScript中的示例代码中,Mortgage对象是示例代码中的Facade。它向客户端提供了一个简单的接口,只有一个方法:applyFor(),但在这个简单的API下面隐藏着相当复杂的操作。

申请人申请贷款,申请人的名字被传递到Mortgage构造函数中,之后调用applyFor方法,并输入申请的贷款金额。在内部,这个方法使用了来自3个独立的子系统的服务,这些子系统很复杂,可能需要一些时间来处理,它们是银行、信用和背景。根据这几个标准(银行账单、信用报告和犯罪背景等),判断是否接受申请人的贷款请求。

<!DOCTYPE html>
<html>
        <head>
                <meta charset="utf-8">
                <title>外观模式:公众号AlbertYang</title>
        </head>
        <body>
        </body>
        <script>
                //抵押贷款
                var Mortgage = function(name) {
                        this.name = name;
                }

                Mortgage.prototype = {
                        //申请贷款
                        applyFor: function(amount) {
                                // 访问多个子系统
                                var result = "批准";
                                if (!new Bank().verify(this.name, amount)) {
                                        result = "拒绝";
                                } else if (!new Credit().get(this.name)) {
                                        result = "拒绝";
                                } else if (!new Background().check(this.name)) {
                                        result = "拒绝";
                                }
                                return this.name + "你的" + amount + " 抵押贷款,已经被" + result;
                        }
                }
                //银行
                var Bank = function() {
                        this.verify = function(name, amount) {
                                // 省略复杂的逻辑代码......
                                return true;
                        }
                }
                //信用
                var Credit = function() {
                        this.get = function(name) {
                                // 省略复杂的逻辑代码......
                                return true;
                        }
                }
                //背景资料
                var Background = function() {
                        this.check = function(name) {
                                // 省略复杂的逻辑代码......
                                return true;
                        }
                }

                function run() {
                        var mortgage = new Mortgage("张三");
                        var result = mortgage.applyFor("100,000元");

                        console.info("%c%s", "color:red; font-size:18px", result);
                }
                run();
</script>
</html>

4 实例应用

4.1 跨浏览器事件

在下面的代码中,我们使用了外观模式通过检测浏览器特性,创建一个跨浏览器的事件监听方法,下面的例子是对input对象添加click事件。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>跨浏览器事件方法:公众号AlbertYang</title>
  </head>
  <body>
    <input type="button" id="myInput" value="提交" />
  </body>
  <script>
    function addEvent(dom, type, fn) {
      if (dom.addEventListener) { // 支持DOM2级事件处理方法的浏览器
        dom.addEventListener(type, fn, false)
      } else if (dom.attachEvent) { // 不支持DOM2级但支持attachEvent
        dom.attachEvent('on' + type, fn)
      } else {
        dom['on' + type] = fn // 都不支持的浏览器
      }
    }

    const myInput = document.getElementById('myInput')
    addEvent(myInput, 'click', function() {
      console.log('绑定 click 事件')
    })
</script>
</html>

4.2 阻止默认和冒泡事件

下面的例子,把阻止冒泡和阻止默认事件放到了外观角色中,其中的stopEvent就是提供给使用者,用来阻止冒泡和默认事件的一个方法。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>阻止默认和冒泡事件:公众号AlbertYang</title>
  </head>
  <body>
    <input type="button" id="myInput" value="提交" />
  </body>
  <script>
    var N = window.N || {};

    N.tools = {
      cancelBubble: function(e) { //取消冒泡
        if (e.stopPropagation) {
          e.stopPropagation();
        } else {
          e.cancelBubble = true; // IE下
        }
      },
      preventDefault: function(e) { // 阻止默认事件
        if (e.preventDefault) {
          e.preventDefault();
        } else {
          e.returnValue = false; // IE下
        }
      },
      stopEvent: function(e) {
        N.tools.cancelBubble(e);
        N.tools.preventDefault(e);
      }
    }

    document.onclick = function(e) {
      console.log('哈哈')
    }

    document.getElementById('myInput').onclick = function(e) {
      N.tools.stopEvent(e)
      console.log('呵呵')
    }
</script>
</html>

5 总结

外观模式在javascript的应用广泛,如果某块代码反复出现,比如函数a的调用基本都出现在函数b的调用之前,那么可以考虑考虑将这块代码使用外观角色包装一下来优化结构。另外对于一些浏览器不兼容的API,最好的方式便是将跨浏览器差异全部集中放置到一个外观模式实例中来提供一个对外接口。另外在软件设计初期,我们应该有意识地将不同的两个层分离,比如经典的三层结构,而在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,增加外观模式可以提供一个简单的接口,减少它们之间的依赖。如果我们正在维护一个遗留的大型系统,我们应该为该系统开发一个外观模式类,给以前设计粗糙和高度复杂的遗留代码提供比较清晰的接口,让新系统和外观对象进行交互。外观模式被开发者连续使用时会产生一定的性能问题,因为在每次调用时都要检测功能的可用性。

今天的学习就到这里,你可以使用今天学习的技巧来改善一下你曾经的代码,如果想继续提高,欢迎关注我,每天学习进步一点点,就是领先的开始。

本文分享自微信公众号 - AlbertYang(AlbertYang666),作者:AlbertYang

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-08-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JavaScript设计模式之外观模式

    – 原来的系统中用户对接每一个子系统 – 使用外观模式之后用户只需要对接外观那个高层接口即可

    w候人兮猗
  • 设计模式之外观模式(Facade Pattern)外观模式的优缺点

    外观模式外部访问内部复杂代码的一个接口,举个例子,我们知道打开一台电脑很简单,只要按开机键,但实际上在后台我们看不到的地方,计算机进行了很多复杂的工作,比如,c...

    desperate633
  • 设计模式之外观模式

    1.外观模式简介 外观模式介绍 当我们开发Android的时候,无论是做SDK还是封装API,我们大多都会用到外观模式,它通过一个外观类使得整个系统的结构只有一...

    用户1269200
  • 设计模式之外观模式

    小编自从毕业后开始做软件开发,做着做着发现不爽了,钱赚不了太多,头发也白了。于是拿着一点小资本,想着做点小生意。瞅着眼前的餐饮行业还不错,于是打算开一家餐馆。开...

    用户1205080
  • 设计模式之 外观模式

    外观模式(又称门面模式),通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性。UML...

    java乐园
  • 设计模式之外观模式

    外观模式(Facade)是23种设计模式之一,也称为门面模式。DP中是这么定义外观模式的:

    端碗吹水
  • 设计模式之外观模式

    Provide a unified interface to a set of interfaces in a subsystem. Facade define...

    beginor
  • Java 设计模式 之 facade(外观)设计模式

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://louluan.blog.c...

    亦山
  • 设计模式----外观模式

    SuperHeroes
  • 设计模式-外观模式

    一般想DIY电脑个性人配置,要么自己来组装(很费劲),要么买在电脑城买好组件找师师傅帮你装,不用理那么多,而外观模式就是类似这种为你组装好的人员。

    逍遥壮士
  • 设计模式-外观模式

    这是我们平时开发用的最多的模式之一,可以说我们每天都在用这个模式在写代码,只是我们可能没有意识到。

    码哥字节
  • 设计模式--外观模式

    最少知识原则:尽量减少对象之间的交互,只留几个“密友” 项目设计中就是不要让太多的类耦合在一起

    HUC思梦
  • 设计模式——外观模式

    设计模式——外观模式

    Java架构师必看
  • Java描述设计模式(12):外观模式

    知了一笑
  • go设计模式之外观模式

    这篇是设计模式中结构模式的第一篇。微服务架构现在是系统的架构的主流,它将系统拆分成一个个独立的服务,服务之间通过通信建立起关联关系。假设现在有一个博客的系统,它...

    暮雨
  • 设计模式之十(外观模式)

    外观模式:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一系统更加容易使用.

    aehyok
  • dart设计模式之外观模式

    外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个...

    Weaster
  • 设计模式 (9)——外观模式(Facade Pattern,结构型)

    使用设计模式可以提高代码的可复用性、可扩充性和可维护性。外观模式(Facade Pattern)属于结构型模式,提供了一个统一的接口(具体类),用来访问子系统的...

    Dabelv
  • 设计模式- 观察者模式(Observer Pattern)

    易兒善

扫码关注云+社区

领取腾讯云代金券