装饰模式:
1、定义:动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活
2、模型结构:
(1)抽象构件(Component):定义一个抽象接口以规范准备接收附加责任的对象
(2)具体构件(ConcreteComponent):实现抽象构件,通过装饰角色为其添加一些职责
(3)抽象装饰类(Decorator):继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能
(4)具体装饰类(ConcreteDecorator):实现抽象装饰的相关方法,并给具体构件对象添加附加的责任
3、优点:
(1)装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性
(2)可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的装饰器实现不同的行为
(3)通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合
(4)具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,
在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”
4、缺点:
(1)使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,
而不是它们的类或者属性值有所不同,同时还将产生很多具体装饰类。
这些装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度
(2)这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,
对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐
5、适用环境:
(1)在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
(2)需要动态地给一个对象增加功能,这些功能也可以动态地被撤销
(3)当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时
注:不能采用继承的情况主要有两类
(1)系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长
(2)因为类定义不能继承(如final类)
// 抽象构件 Component interface IPerson { getName(): string; } // 具体构件 ConcreteComponent,继承抽象构件 class Tim implements IPerson { private name: string; getName(): string { this.name = "Tim"; return this.name; } } // 抽象装饰类 Decorator,继承抽象构件,并聚合抽象构件 class Cloths implements IPerson { protected person: IPerson; constructor(person: IPerson) { this.person = person; } getName(): string { return this.person.getName(); } } class Trousers implements IPerson { protected person: IPerson; constructor(person: IPerson) { this.person = person; } getName(): string { return this.person.getName(); } } // 具体装饰类 ConcreteDecorator,继承抽象装饰类 class Suit extends Cloths { private info: string; constructor(person: IPerson) { super(person); } getCloths(): string { this.info = this.person.getName() + "上衣: " + "suit..."; return this.info; } } class Jack extends Cloths { private info: string; constructor(person: IPerson) { super(person); } getCloths(): string { this.info = this.person.getName() + "上衣: " + "jacket..."; return this.info; } } class Pants extends Trousers { private info: string; constructor(person: IPerson) { super(person); } getTrousers(): string { this.info = this.person.getName() + "裤子: " + "pants..."; return this.info; } } class Jean extends Trousers { private info: string; constructor(person: IPerson) { super(person); } getTrousers(): string { this.info = this.person.getName() + "裤子: " + "jean..."; return this.info; } } let tim: IPerson = new Tim(); console.log("Get suit"); let suit: Suit = new Suit(tim); console.log(suit.getCloths()); // Tim上衣: suit... console.log("Get jean"); let jean: Jean = new Jean(tim); console.log(jean.getTrousers()); // Tim裤子: jean...
外观模式:
1、定义:外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,
外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用
2、模型结构:
(1)外观角色(Facade):为多个子系统对外提供一个共同的接口
(2)子系统角色(SubSystem):实现系统的部分功能,客户可以通过外观角色访问它
3、优点:
(1)对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易
(2)降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类
(3)降低了大型软件系统中的编译依赖性,简化了系统在不同平台之间的移植过程,
因为编译一个子系统不会影响其他的子系统,也不会影响外观对象
(4)只是提供了一