作者:@Agbo, Daniel Onuoha
原文:https://dev.to/shieldstring/adapter-and-composite-design-patterns-4701
背景
在软件工程中,设计模式是解决常见问题的可重用解决方案。结构型设计模式专注于如何将类和对象组合成更大的结构。本文深入探讨了两种常见的结构型设计模式:适配器模式(Adapter Pattern)和组合模式(Composite Pattern)。这两种模式在处理不同类型的软件设计问题时非常有用,尤其是在需要灵活性和统一性的场景中。
要点
1、适配器模式:
用于将一个现有类的接口转换成系统期望的接口, 充当了两个不兼容接口之间的桥梁, 使它们能够协同工作。
2、组合模式:用于以统一的方式处理单个对象和对象组合。此模式允许你构建表示部分 - 整体层次结构的树状结构, 其中叶对象和组合对象都被客户端以相同的方式对待。
分析
1、适配器模式
场景
当你需要将第三方库或遗留系统集成到当前代码中, 但第三方代码的接口与系统期望的接口不匹配时, 适配器模式可以帮助你 "适配" 现有代码以满足新系统的要求, 同时无需修改原始代码。
【第2896期】插件化设计模式在前端领域的应用
关键组件
客户端 (Client): 需要特定功能但期望特定接口的系统或应用程序。
适配者 (Adaptee): 提供所需功能但接口不匹配的现有类或系统。
适配器 (Adapter): 将适配者的接口转换为客户端期望的接口的类。
示例
假设你有一个通过 PayPal 处理支付的现有类, 但现在需要将其集成到一个期望 Stripe 支付接口的系统中。以下是适配器模式如何提供帮助:
// Adaptee: 现有的 PayPal 支付系统
class PayPalPayment {
pay(amount) {
console.log(`Paying $${amount} using PayPal.`);
}
}
// Target Interface: 系统期望的类似 Stripe 的支付接口
class StripePayment {
processPayment(amount) {
console.log(`Paying $${amount} using Stripe.`);
}
}
// Adapter: 将 PayPal 适配到 Stripe 的接口
class PayPalAdapter extends StripePayment {
constructor(paypal) {
super();
this.paypal = paypal;
}
processPayment(amount) {
this.paypal.pay(amount);
}
}
// Client: 使用 StripePayment 接口
const paymentSystem = new PayPalAdapter(new PayPalPayment());
paymentSystem.processPayment(100);
适配器模式的优势
灵活性:你可以重用现有类而无需修改其代码, 这在使用第三方库时非常有用。
单一职责原则:适配器模式允许清晰地分离关注点。适配器专注于转换接口, 而客户端和适配者则执行各自的角色。
松耦合:客户端和适配者是松耦合的, 允许你轻松地替换或升级组件。
何时使用
2、组合模式
场景
假设你正在设计一个图形编辑器, 用户可以在其中绘制基本形状(如圆形和矩形)并将它们组合成更复杂的形状。复杂形状由单个形状组成, 但你希望以相同的方式处理单个形状和组合形状。
【图书】漫画设计模式
关键组件
组件 (Component): 声明单个对象和组合对象的通用操作的接口。
叶 (Leaf): 实现组件接口的单个对象。这些是基本构建块(例如, 单个形状)。
组合 (Composite): 保存多个叶对象的 对象。组合也实现了组件接口, 允许客户端将其视为叶对象。
示例
让我们以图形编辑器示例为例, 在该示例中, 我们希望以统一的方式处理单个形状和形状组:
// Component: 单个对象和组合对象的通用接口
class Graphic {
draw() {}
}
// Leaf: 表示单个形状
class Circle extends Graphic {
draw() {
console.log(" Drawing a Circle ");
}
}
class Rectangle extends Graphic {
draw() {
console.log(" Drawing a Rectangle ");
}
}
// Composite: 表示形状组
class CompositeGraphic extends Graphic {
constructor() {
super();
this.graphics = [];
}
add(graphic) {
this.graphics.push(graphic);
}
remove(graphic) {
this.graphics = this.graphics.filter(g => g !== graphic);
}
draw() {
for (const graphic of this.graphics) {
graphic.draw();
}
}
}
// Client: 使用单个对象和组合对象
const circle = new Circle();
const rectangle = new Rectangle();
const composite = new CompositeGraphic();
composite.add(circle);
composite.add(rectangle);
composite.draw(); // 输出: Drawing a Circle, Drawing a Rectangle
组合模式的优势
一致性:组合模式允许客户端以统一的方式处理单个对象和组合。你可以以相同的方式处理叶对象和组合对象, 而无需编写条件代码。
简化客户端代码:由于单个对象和组合对象共享相同的接口, 因此客户端代码变得更简单, 更易于管理。
可扩展性:通过添加新的叶或组合组件可以轻松扩展系统, 而不会影响客户端代码。
何时使用
结论
适配器模式和组合模式是软件开发中非常重要的工具,尤其是在需要灵活性和统一性的场景中。适配器模式适用于集成不兼容的接口,而组合模式则适用于处理树形结构。理解和应用这些模式可以显著提高应用程序的可维护性、灵活性和可扩展性,是构建健壮软件系统的关键。
😀 每天只需花五分钟即可阅读到的技术资讯,加入【早阅】共学,可联系 vx:zhgb_f2er
5 分钟新知:了解技术资讯的一种方式。
🚀可直接通过阅读原文了解详细内容。