【利用AI让知识体系化】7种结构型模式(一)https://developer.aliyun.com/article/1426100
桥接模式
桥接模式(Bridge Pattern)是一种结构型设计模式,它允许你将抽象部分与实现部分分离,使得它们可以独立地变化。在桥接模式中,我们将一个对象的实现与其抽象进行分离,从而使得它们可以单独进行变化,而不会相互影响。
一个简单的桥接模式的例子是:我们有一个电视机和多个遥控器,它们之间的关系是一对多的关系。我们可以使用桥接模式来将这个关系进行抽象,从而让一个电视机对象可以与多个遥控器对象进行关联,并且可以随时切换遥控器,而不会影响电视机对象的状态和行为。
下面是使用 JavaScript 实现的简单的桥接模式的示例:
// 抽象遥控器类 class RemoteControl { constructor(tv) { this.tv = tv; } on() { this.tv.on(); } off() { this.tv.off(); } setChannel(channel) { this.tv.setChannel(channel); } } // 具体遥控器类 class BasicRemoteControl extends RemoteControl { constructor(tv) { super(tv); } } class AdvancedRemoteControl extends RemoteControl { constructor(tv) { super(tv); } setVolume(volume) { this.tv.setVolume(volume); } } // 抽象电视机类 class TV { constructor() {} on() {} off() {} setChannel(channel) {} } // 具体电视机类 class SonyTV extends TV { constructor() { super(); this.channel = 1; } on() { console.log('Sony TV is turned on'); } off() { console.log('Sony TV is turned off'); } setChannel(channel) { this.channel = channel; console.log(`Sony TV channel is set to ${channel}`); } } class SamsungTV extends TV { constructor() { super(); this.channel = 1; } on() { console.log('Samsung TV is turned on'); } off() { console.log('Samsung TV is turned off'); } setChannel(channel) { this.channel = channel; console.log(`Samsung TV channel is set to ${channel}`); } setVolume(volume) { console.log(`Samsung TV volume is set to ${volume}`); } } // 客户端代码 const sonyTV = new SonyTV(); const samsungTV = new SamsungTV(); const basicRemote = new BasicRemoteControl(sonyTV); basicRemote.on(); basicRemote.setChannel(4); basicRemote.off(); const advancedRemote = new AdvancedRemoteControl(samsungTV); advancedRemote.on(); advancedRemote.setChannel(7); advancedRemote.setVolume(15); advancedRemote.off();
在这个示例中,定义了一个抽象遥控器类 RemoteControl
和一个抽象电视机类 TV
。
然后又定义了两个具体遥控器类 BasicRemoteControl
和 AdvancedRemoteControl
,以及两个具体电视机类 SonyTV
和 SamsungTV
。
组合模式
组合模式(Composite Pattern)是一种结构型设计模式,它能够将对象组合成树形结构,并且能像使用独立对象一样使用其中的任何一个对象。在组合模式中,我们可以将对象组合成树形结构以表示 “部分-整体” 的层次结构,同时还能让客户端以统一的方式对待单个对象和组合对象。
一个简单的组合模式的例子是:我们有一个组织机构,包括多个部门和员工。我们可以使用组合模式来表示这种 “部分-整体” 的层次结构,并且能够统一地对待部门和员工。
下面是使用 JavaScript 实现的简单的组合模式的示例:
// 抽象组件类 class OrganizationComponent { constructor(name) { this.name = name; } getName() { return this.name; } print() {} } // 具体部门类 class Department extends OrganizationComponent { constructor(name) { super(name); this.children = []; } add(component) { this.children.push(component); } remove(component) { const index = this.children.indexOf(component); if(index !== -1) { this.children.splice(index, 1); } } print() { console.log(`Department: ${this.getName()}`); for(let child of this.children) { child.print(); } } } // 具体员工类 class Employee extends OrganizationComponent { constructor(name) { super(name); } print() { console.log(`Employee: ${this.getName()}`); } } // 客户端代码 const organization = new Department('Headquarter'); const financeDept = new Department('Finance Department'); financeDept.add(new Employee('Alice')); financeDept.add(new Employee('Bob')); const salesDept = new Department('Sales Department'); salesDept.add(new Employee('Charlie')); salesDept.add(new Employee('David')); organization.add(financeDept); organization.add(salesDept); organization.print();
在这个示例中,我们定义了一个抽象组件类 OrganizationComponent
和两个具体的类 Department
和 Employee
。具体部门类 Department
内部维护一个员工列表,同时还实现了添加、删除和打印子组件的方法。具体员工类 Employee
重写了 print()
方法用于输出员工姓名。
在客户端代码中,我们创建了一个总部部门 Headquarter
,然后又分别创建了财务部门 Finance Department
和销售部门 Sales Department
。其中,财务部门又包括了员工 Alice
和员工 Bob
;销售部门又包括了员工 Charlie
和员工 David
。
享元模式
享元模式(Flyweight Pattern)是一种结构型设计模式,它可以减少程序中的对象数量,通过共享相同对象的方式来减少内存和计算资源的开销。该模式的主要思路是将一个对象的状态拆分成内部状态和外部状态两部分,内部状态作为对象的固有属性进行共享复用,外部状态则通过参数的方式传递进来,每个独立对象可以重用内部状态,拥有自己独有的外部状态。
以下是JS中的一个享元模式的示例代码:
// 定义一个享元工厂对象 var FlyweightFactory = (function () { var flyweights = {}; return { get: function (key) { if (!flyweights[key]) { flyweights[key] = new Flyweight(key); } return flyweights[key]; }, getCount: function () { var count = 0; for (var f in flyweights) count++; return count; } }; })(); // 定义一个享元对象 function Flyweight (name) { this.name = name; } Flyweight.prototype.execute = function (state) { console.log(`Flyweight ${this.name}, state: ${state}`); }; // 定义一个客户端对象 function Client (name, state) { this.flyweight = FlyweightFactory.get(name); this.state = state; } Client.prototype.execute = function () { this.flyweight.execute(this.state); }; // 客户端调用 var client1 = new Client('flyweight1', 'state1'); client1.execute(); // Flyweight flyweight1, state: state1 var client2 = new Client('flyweight2', 'state2'); client2.execute(); // Flyweight flyweight2, state: state2 console.log(`共创建了 ${FlyweightFactory.getCount()} 个享元对象`);
在上述代码中,我们通过工厂对象FlyweightFactory创建享元对象Flyweight,并通过客户端对象Client在需要使用时获取享元对象。由于享元对象Flyweight的内部状态是可以共享的,因此我们只需要在需要使用时获取相应的享元对象,而不需要多次创建。这样可以节省内存和计算资源的开销。