设计模式:TypeScript中的外观模式

门面模式为一组复杂的子系统接口提供了一个更高级的统一接口,通过它可以更容易地访问子系统接口。

欢迎来到 TypeScript 设计模式系列,该系列介绍了使用 TypeScript 进行 Web 开发的一些有用的设计模式。

 之前的文章如下:

设计模式对于 web 开发人员来说非常重要,掌握它们可以让我们写出更好的代码。在本文中,我将使用 TypeScript 来介绍 Facade 模式。

Facade 模式为一组复杂的子系统接口提供了一个更高级的统一接口,通过它可以更容易地访问子系统接口,它可以通过引入一个新的 Facade 类来降低原始系统的复杂性,并减少客户机类和子系统类之间的耦合。

Facade 模式要求子系统外部和内部之间的通信通过统一的 Facade 对象进行,Facade 类将客户机与子系统的内部复杂性分离开来,以便客户机只需要处理 Facade 对象,而不需要处理子系统内部的许多对象。

接下来,我将介绍如何使用 Facade 模式,以便更容易地访问子系统接口。为了更好地理解下面的代码,让我们先看看相应的 UML 图:

Facade模式包括以下角色:

  • 外观:ShapeFacade

  • 子系统:圆形、矩形、三角形

接下来,让我们定义  Shape  接口和三个实现该接口的类,以表示不同的形状。

interface Shape {  draw(): void;}class Circle implements Shape {  draw(): void {    console.log("Draw circle");  }}class Rectangle implements Shape {  draw(): void {    console.log("Draw rectangle");  }}class Triangle implements Shape {  draw(): void {    console.log("Draw triangle");  }}

定义了不同的形状类之后,让我们创建  ShapeFacade  类:

class ShapeFacade {  private circle: Shape;  private rectangle: Shape;  private triangle: Shape;  constructor() {    this.circle = new Circle();    this.rectangle = new Rectangle();    this.triangle = new Triangle();  }  public drawCircle(): void {    this.circle.draw();  }  public drawRectangle(): void {    this.rectangle.draw();  }  public drawTriangle(): void {    this.triangle.draw();  }}

通过  ShapeFacade  类,Client 对象可以使用  ShapeFacade  对象绘制不同的形状。

class Client {  private shapeFacade: ShapeFacade;  constructor() {    this.shapeFacade = new ShapeFacade();  }  drawShapes() {    this.shapeFacade.drawCircle();    this.shapeFacade.drawRectangle();    this.shapeFacade.drawTriangle();  }}const client = new Client();client.drawShapes();

为了帮助您更好地理解立面图案的作用,我们用一张图片来展示不使用立面图案和使用立面图案的区别:

在Web项目中,Facade模式的一个常见用例是处理浏览器Web API的兼容性。例如,在不同的浏览器环境中处理事件监听:

function addHandler(element, type, handler) {  if (element.addEventListener) {    element.addEventListener(type, handler, false);  } else if (element.attachEvent) {    element.attachEvent("on" + type, handler);  } else {    element["on" + type] = handler;  }}

在上面的代码中,我们实现了对不同浏览器添加事件监听器的处理,代码实现起来也很简单,但是有一个问题,就是每次调用的时候都需要判断,这显然是不合理的,对于上面的问题,我们可以通过lazy loading functions来解决。

所谓惰性加载,就是当函数第一次被调用时根据条件执行,第二次被调用时不再判断条件,直接执行函数。

为了实现这个函数,我们可以在满足第一个条件判断的分支中重写被调用的函数:

function addHandler(element, type, handler) {  if (element.addEventListener) {    addHandler = function (element, type, handler) {      element.addEventListener(type, handler, false);    };  } else if (element.attachEvent) {    addHandler = function (element, type, handler) {      element.attachEvent("on" + type, handler);    };  } else {    addHandler = function (element, type, handler) {      element["on" + type] = handler;    };  }  // Ensure that the first call can perform monitoring normally  return addHandler(element, type, handler);}

除了使用上面的方法,我们还可以使用自执行函数来实现惰性加载:

const addHandler = (function () {  if (document.addEventListener) {    return function (element, type, handler) {      element.addEventListener(type, handler, false);    };  } else if (document.attachEvent) {    return function (element, type, handler) {      element.attachEvent("on" + type, handler);    };  } else {    return function (element, type, handler) {      element["on" + type] = handler;    };  }})();

最后,我们来总结一下外观模式的使用场景:

  • 客户端程序与多个子系统之间存在着很强的依赖关系,引入facade类可以将子系统与客户端和其他子系统解耦,从而提高子系统的独立性和可移植性。

  • 在分层结构中,facade模式可以用于定义系统中每个层的入口点,而不是在层之间创建直接连接,而是通过facade类建立连接,减少层之间的耦合。


如果您有任何问题,请随时给我留言。我以后会继续介绍其他的模式,如果您感兴趣,

 欢迎关注公众号:文本魔术,了解更多

  • 43
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值