从前端视角看设计模式之结构型模式篇

上篇我们介绍了 设计模式之创建型模式篇,接下来介绍设计模式之结构型模式篇

适配器模式

适配器模式旨在解决接口不兼容的问题,它通过创建一个适配器类,将源对象的接口转换成目标接口,从而使得不兼容的接口能够协同工作。简单来说,适配器模式的目标就是将一个接口转化成客户端所期望的接口,通过这种方式,现有的类(或者第三方类)可以在不修改的情况下被重用


它的使用场景主要有以下几个:

1)需要使用现有类,但其接口不符合系统需求

2)希望创建一个可复用的类,与多个不相关的类一起工作,这些类可能没有统一的接口

3)通过接口转换,将一个类集成到另一个类系中


适配器模式包含以下几个主要角色:

1)目标接口

定义客户需要的接口

2)适配者类

定义一个已经存在的接口,这个接口需要适配

3)适配器类

实现目标接口,并通过组合或继承的方式调用适配者类中的方法,从而实现目标接口


通过以下这个例子来理解适配器模式,假设有一个支付系统,系统中既有旧的支付接口OldPaymentSystem,也有新的支付接口NewPaymentSystem,我们希望使用一个统一的接口来调用这两个不同的支付系统

1)定义目标接口

目标接口是客户端期望使用的接口,所有支付系统都应当提供一个pay()方法

// 目标接口(Target)
class PaymentGateway {
    pay(amount) {
        throw new Error("该方法需要被重写")
    }
}

2)定义源接口

源接口是现有的不兼容接口,假设现有的支付系统使用的是OldPaymentSystem,它提供了一个makePayment()方法,而不是pay()

// 源接口:旧支付系统(Adaptee)
class OldPaymentSystem {
    makePayment(amount) {
      console.log(`使用旧支付系统支付:${amount} 元`)
    }
}

3)创建适配器

适配器的作用是将OldPaymentSystem的接口适配到PaymentGateway接口,使得它们能够通过相同的接口来使用

// 适配器:将旧支付系统适配为目标接口
class OldPaymentAdapter extends PaymentGateway {
    constructor(oldPaymentSystem) {
      super()
      this.oldPaymentSystem = oldPaymentSystem
    }
    // 实现目标接口的 pay 方法
    pay(amount) {
      this.oldPaymentSystem.makePayment(amount)  // 调用旧支付系统的方法
    }
}

4)创建新支付系统

新支付系统与目标接口兼容,直接实现pay()方法

// 新支付系统(NewPaymentSystem)
class NewPaymentSystem extends PaymentGateway {
    pay(amount) {
      console.log(`使用新支付系统支付:${amount} 元`)
    }
}

5)使用适配器模式

客户端只依赖于PaymentGateway接口来进行支付,而不关心支付系统的实现,无论使用的是旧的支付系统还是新的支付系统,客户端代码都会通过统一的接口pay()来进行支付

// 客户端代码:使用支付网关接口
function processPayment(paymentSystem, amount) {
    paymentSystem.pay(amount)  // 使用支付系统进行支付
}
  
// 客户端代码使用旧支付系统
const oldPaymentSystem = new OldPaymentSystem()
const adaptedOldPaymentSystem = new OldPaymentAdapter(oldPaymentSystem) // 使用适配器
processPayment(adaptedOldPaymentSystem, 100)
// 客户端代码使用新支付系统
const newPaymentSystem = new NewPaymentSystem()
processPayment(newPaymentSystem, 200)

执行代码,运行结果如下:

在这里插入图片描述

桥接模式

桥接模式通过将一个对象的抽象部分与它的实现部分分离,使它们可以独立变化,通过组合的方式,而不是继承的方式,将抽象和实现的部分连接起来


它的使用场景主要有以下:

1)当需要抽象和实现分离,且两者独立变化时

2)当系统不希望固定抽象类和实现类的绑定时

3)当多个类的不同实现有类似的功能时


桥接模式包含以下几个主要角色:

1)抽象类

定义抽象接口,通常包含对实现接口的引用

2)扩展抽象类

对抽象的扩展,可以是抽象的子类或具体实现类

3)实现类

定义具体实现类必须遵循的接口,通常包含一些基本操作

4)具体实现

实现实现接口的具体类


通过以下绘制图形的例子来展示桥接模式,图形有不同的形状(如圆形和矩形),而每个图形可以有不同的绘制方式

1)定义实现接口

定义一个接口DrawingAPI,它包含绘制图形的基本方法

// 实现类接口:绘制API
class DrawingAPI {
    drawCircle(radius, x, y) {
      throw new Error("该方法需要被重写")
    }
    drawRectangle(width, height, x, y) {
      throw new Error("该方法需要被重写")
    }
}

2)创建具体实现类

DrawingAPI接口创建几个具体实现类,例如,一个实现类使用Canvas来绘制图形,另一个实现类使用SVG来绘制

// 具体实现类:使用 Canvas 绘制图形
class CanvasDrawingAPI extends DrawingAPI {
    drawCircle(radius, x, y) {
      console.log(`在 Canvas 上绘制圆形,半径:${radius}, 位置:(${x}, ${y})`)
    }
    drawRectangle(width, height, x, y) {
      console.log(`在 Canvas 上绘制矩形,宽度:${width}, 高度:${height}, 位置:(${x}, ${y})`)
    }
}
  
// 具体实现类:使用 SVG 绘制图形
class SVGDrawingAPI extends DrawingAPI {
    drawCircle(radius, x, y) {
      console.log(`在 SVG 上绘制圆形,半径:${radius}, 位置:(${x}, ${y})`)
    }
    drawRectangle(width, height, x, y) {
      console.log(`在 SVG 上绘制矩形,宽度:${width}, 高度:${height}, 位置:(${x}, ${y})`)
    }
}

3)定义抽象类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值