代理(Proxy)

模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。

ES6

  1. class Proxys {
  2. constructor(){
  3. this.realSubject = new RealSubject();
  4. }
  5. Request() {
  6. this.preRequest();
  7. this.realSubject.Request();
  8. this.postRequest();
  9. }
  10. preRequest() {
  11. console.log('访问真实之前');
  12. }
  13. postRequest() {
  14. console.log('访问真实之后');
  15. }
  16. }
  17. class RealSubject {
  18. Request() {
  19. console.log('真实的')
  20. }
  21. }
  22. function proxyTest() {
  23. const proxy = new Proxys()
  24. proxy.Request();
  25. }
  26. proxyTest();
  27. // 或者
  28. let Flower = function() {}
  29. let xiaoming = {
  30. sendFlower: function(target) {
  31. let flower = new Flower()
  32. target.receiveFlower(flower)
  33. }
  34. }
  35. let B = {
  36. receiveFlower: function(flower) {
  37. A.listenGoodMood(function() {
  38. A.receiveFlower(flower)
  39. })
  40. }
  41. }
  42. let A = {
  43. receiveFlower: function(flower) {
  44. console.log('收到花'+ flower)
  45. },
  46. listenGoodMood: function(fn) {
  47. setTimeout(function() {
  48. fn()
  49. }, 1000)
  50. }
  51. }
  52. xiaoming.sendFlower(B)

Typescript

  1. interface motheds {
  2. Request(): void;
  3. }
  4. class Proxys implements motheds {
  5. realSubject: RealSubject;
  6. constructor(){
  7. this.realSubject = new RealSubject();
  8. }
  9. Request() {
  10. this.preRequest();
  11. this.realSubject.Request();
  12. this.postRequest();
  13. }
  14. preRequest() {
  15. console.log('访问真实之前');
  16. }
  17. postRequest() {
  18. console.log('访问真实之后');
  19. }
  20. }
  21. class RealSubject implements motheds {
  22. Request() {
  23. console.log('真实的')
  24. }
  25. }
  26. function proxyTest() {
  27. const proxy = new Proxys()
  28. proxy.Request();
  29. }
  30. proxyTest();

代理模式的主要优点有:

  • 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用
  • 代理对象可以扩展目标对象的功能;
  • 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度;

其主要缺点是:

  • 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢
  • 增加了系统的复杂度

    适配器(Adapter)

    模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

ES6

  1. class Adaptee {
  2. specificRequest() {
  3. console.log('适配者中的被调用!');
  4. }
  5. }
  6. class ClassAdapter extends Adaptee {
  7. request() {
  8. this.specificRequest();
  9. }
  10. }
  11. const ClassAdapterTest = new ClassAdapter();
  12. ClassAdapterTest.request();

Typescript

  1. interface Target {
  2. request(): void;
  3. }
  4. class Adaptee {
  5. specificRequest() {
  6. console.log('适配者中的被调用!');
  7. }
  8. }
  9. class ClassAdapter extends Adaptee implements Target{
  10. request() {
  11. this.specificRequest();
  12. }
  13. }
  14. const ClassAdapterTest = new ClassAdapter();
  15. ClassAdapterTest.request();

该模式的主要优点如下。

  • 客户端通过适配器可以透明地调用目标接口。
  • 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
  • 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。

其缺点是:对类适配器来说,更换适配器的实现过程比较复杂。

桥接(Bridge)

模式:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

ES6

  1. // 具体实现化角色
  2. class ConcreteImplementorA {
  3. operationImpl() {
  4. console.log('具体实现化角色');
  5. this.addOperationImpl();
  6. }
  7. addOperationImpl() {
  8. console.log('具体实现化角色 - 增加功能');
  9. }
  10. }
  11. // 扩展抽象化角色
  12. class RefinedAbstraction {
  13. constructor(implementation) {
  14. this.implementation = implementation;
  15. }
  16. operation() {
  17. console.log('扩展了实现化角色能力');
  18. this.implementation.operationImpl();
  19. }
  20. }
  21. const concreteImplementorATest = new ConcreteImplementorA();
  22. const refinedAbstractionTest = new RefinedAbstraction(concreteImplementorATest);
  23. refinedAbstractionTest.operation();

Typescript

  1. interface Implementor {
  2. operationImpl(): void;
  3. addOperationImpl():void
  4. }
  5. // 具体实现化角色
  6. class ConcreteImplementorA implements Implementor {
  7. operationImpl() {
  8. console.log('具体实现化角色');
  9. this.addOperationImpl();
  10. }
  11. addOperationImpl() {
  12. console.log('具体实现化角色 - 增加功能');
  13. }
  14. }
  15. abstract class Abstraction {
  16. implementation!: Implementor;
  17. constructor(implementation:Implementor) {
  18. }
  19. abstract operation():void
  20. }
  21. // 扩展抽象化角色
  22. class RefinedAbstraction extends Abstraction {
  23. constructor(implementation:Implementor) {
  24. super(implementation);
  25. this.implementation = implementation;
  26. }
  27. operation() {
  28. console.log('扩展了实现化角色能力');
  29. this.implementation.operationImpl();
  30. }
  31. }
  32. const concreteImplementorATest = new ConcreteImplementorA();
  33. const refinedAbstractionTest = new RefinedAbstraction(concreteImplementorATest);
  34. refinedAbstractionTest.operation();

桥接(Bridge)模式的优点是:

  • 由于抽象与实现分离,所以扩展能力强;
  • 其实现细节对客户透明。

缺点是:由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,这增加了系统的理解与设计难度。

装饰(Decorator)

模式:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。

ES6

  1. class ConcreteComponent {
  2. operation() {
  3. console.log('ConcreteComponent - 组件功能');
  4. }
  5. }
  6. class ConcreteDecorator {
  7. constructor(components) {
  8. this.components = components;
  9. }
  10. operation() {
  11. console.log('装饰者增加力功能了');
  12. this.components.operation();
  13. this.addFn();
  14. }
  15. addFn() {
  16. console.log('增加力功能了');
  17. }
  18. }
  19. function clientTest() {
  20. const p = new ConcreteComponent();
  21. p.operation();
  22. const concreteDecorator = new ConcreteDecorator(p);
  23. concreteDecorator.operation();
  24. }
  25. clientTest();

Typescript

  1. interface motheds {
  2. operation(): void;
  3. }
  4. interface concreteDecorator{
  5. addFn():void
  6. }
  7. class ConcreteComponent implements motheds {
  8. operation() {
  9. console.log('ConcreteComponent - 组件功能');
  10. }
  11. }
  12. class ConcreteDecorator implements motheds, concreteDecorator {
  13. components: motheds;
  14. constructor(components:motheds) {
  15. this.components = components;
  16. }
  17. operation() {
  18. console.log('装饰者增加力功能了');
  19. this.components.operation();
  20. this.addFn();
  21. }
  22. addFn() {
  23. console.log('增加力功能了');
  24. }
  25. }
  26. function clientTest() {
  27. const p = new ConcreteComponent();
  28. p.operation();
  29. const concreteDecorator = new ConcreteDecorator(p);
  30. concreteDecorator.operation();
  31. }
  32. clientTest();

装饰(Decorator)模式的主要优点有:

  • 采用装饰模式扩展对象的功能比采用继承方式更加灵活。
  • 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合。

其主要缺点是:装饰模式增加了许多子类,如果过度使用会使程序变得很复杂。

外观(Facade)

模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。

ES6

  1. class Facade {
  2. system1 = new Subsystem1();
  3. system2 = new Subsystem2();
  4. system3 = new Subsystem3();
  5. method(){
  6. this.system1.methods();
  7. this.system2.methods();
  8. this.system3.methods()
  9. }
  10. }
  11. class Subsystem1 {
  12. methods() {
  13. console.log('系统1');
  14. }
  15. }
  16. class Subsystem2 {
  17. methods() {
  18. console.log('系统2');
  19. }
  20. }
  21. class Subsystem3 {
  22. methods() {
  23. console.log('系统3');
  24. }
  25. }
  26. const facadeTest = new Facade();
  27. facadeTest.method();

Typescript

  1. interface system {
  2. methods(): void;
  3. }
  4. class Facade {
  5. system1 = new Subsystem1();
  6. system2 = new Subsystem2();
  7. system3 = new Subsystem3();
  8. method(){
  9. this.system1.methods();
  10. this.system2.methods();
  11. this.system3.methods()
  12. }
  13. }
  14. class Subsystem1 implements system{
  15. methods() {
  16. console.log('系统1');
  17. }
  18. }
  19. class Subsystem2 implements system{
  20. methods() {
  21. console.log('系统2');
  22. }
  23. }
  24. class Subsystem3 implements system{
  25. methods() {
  26. console.log('系统3');
  27. }
  28. }
  29. const facadeTest = new Facade();
  30. facadeTest.method();

外观(Facade)模式是“迪米特法则”的典型应用,它有以下主要优点。

  1. 降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类。
  2. 对客户屏蔽了子系统组件,减少了客户处理的对象数目,并使得子系统使用起来更加容易。
  3. 降低了大型软件系统中的编译依赖性,简化了系统在不同平台之间的移植过程,因为编译一个子系统不会影响其他的子系统,也不会影响外观对象。

外观(Facade)模式的主要缺点如下。

  1. 不能很好地限制客户使用子系统类。
  2. 增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。

    享元(Flyweight)

    模式:运用共享技术来有效地支持大量细粒度对象的复用。 使用场景:资源池、线程池、缓存池、链接池

ES6

  1. class ConcreteFlyweight {
  2. constructor() {
  3. console.log('哈哈被创建力');
  4. }
  5. operation(key){
  6. console.log('哈哈享元模式设置力了' + key);
  7. }
  8. }
  9. class FlyweightFactory {
  10. constructor() {
  11. this.flyweightInstance = null
  12. }
  13. getFlyweight(key) {
  14. if(this.flyweightInstance) {
  15. this.flyweightInstance.operation(key);
  16. } else {
  17. this.flyweightInstance = new ConcreteFlyweight();
  18. this.flyweightInstance.operation(key);
  19. }
  20. }
  21. }
  22. class unFlyweightFactory {
  23. constructor() {
  24. this.flyweightInstance = null
  25. }
  26. getFlyweight(key) {
  27. this.flyweightInstance = new ConcreteFlyweight();
  28. this.flyweightInstance.operation(key);
  29. }
  30. }
  31. const flyweightFactoryText = new FlyweightFactory();
  32. flyweightFactoryText.getFlyweight('a');
  33. flyweightFactoryText.getFlyweight('b');
  34. flyweightFactoryText.getFlyweight('c');
  35. flyweightFactoryText.getFlyweight('e');
  36. const unFlyweightFactoryText = new unFlyweightFactory();
  37. unFlyweightFactoryText.getFlyweight('a');
  38. unFlyweightFactoryText.getFlyweight('b');
  39. unFlyweightFactoryText.getFlyweight('c');
  40. unFlyweightFactoryText.getFlyweight('e');

Typescript

  1. interface concreteFlyweightMotheds{
  2. operation(key:string): void;
  3. }
  4. abstract class WeightFactory {
  5. flyweightInstance: concreteFlyweightMotheds|undefined;
  6. constructor() {
  7. }
  8. abstract getFlyweight(key:string):void
  9. }
  10. class ConcreteFlyweight implements concreteFlyweightMotheds{
  11. constructor() {
  12. console.log('哈哈被创建力');
  13. }
  14. operation(key:string){
  15. console.log('哈哈享元模式设置力了' + key);
  16. }
  17. }
  18. class FlyweightFactory extends WeightFactory {
  19. constructor() {
  20. super();
  21. }
  22. getFlyweight(key:string) {
  23. if(this.flyweightInstance) {
  24. this.flyweightInstance.operation(key);
  25. } else {
  26. this.flyweightInstance = new ConcreteFlyweight();
  27. this.flyweightInstance.operation(key);
  28. }
  29. }
  30. }
  31. class unFlyweightFactory extends WeightFactory{
  32. constructor() {
  33. super();
  34. }
  35. getFlyweight(key:string) {
  36. this.flyweightInstance = new ConcreteFlyweight();
  37. this.flyweightInstance.operation(key);
  38. }
  39. }
  40. const flyweightFactoryText = new FlyweightFactory();
  41. flyweightFactoryText.getFlyweight('a');
  42. flyweightFactoryText.getFlyweight('b');
  43. flyweightFactoryText.getFlyweight('c');
  44. flyweightFactoryText.getFlyweight('e');
  45. const unFlyweightFactoryText = new unFlyweightFactory();
  46. unFlyweightFactoryText.getFlyweight('a');
  47. unFlyweightFactoryText.getFlyweight('b');
  48. unFlyweightFactoryText.getFlyweight('c');
  49. unFlyweightFactoryText.getFlyweight('e');

享元模式的主要优点是:相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。
其主要缺点是:

  1. 为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。
  2. 读取享元模式的外部状态会使得运行时间稍微变长。

    组合(Composite)

    模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。 一致性,除了访问方法相同,组合调用的方法也是一样的。

ES6

  1. class Leaf {
  2. constructor(name) {
  3. this.name = name;
  4. }
  5. operation() {
  6. console.log('树叶被访问了' + this.name);
  7. }
  8. }
  9. class Composite {
  10. constructor() {
  11. this.childrenList = []
  12. }
  13. add(part) {
  14. this.childrenList.push(part);
  15. }
  16. operation() {
  17. this.childrenList.forEach((child) => {
  18. child.operation();
  19. })
  20. }
  21. }
  22. const composite1 = new Composite();
  23. const composite2 = new Composite();
  24. const leaf1 = new Leaf('a');
  25. const leaf2 = new Leaf('b');
  26. const leaf3 = new Leaf('c');
  27. composite1.add(leaf1);
  28. composite1.add(composite2);
  29. composite2.add(leaf2);
  30. composite2.add(leaf3);
  31. composite1.operation();

Typescript

  1. interface leaCon {
  2. new(name:string):composite
  3. }
  4. interface composite {
  5. operation():void
  6. }
  7. class Leaf implements composite {
  8. name:string
  9. constructor(name:string) {
  10. this.name = name;
  11. }
  12. operation() {
  13. console.log('树叶被访问了' + this.name);
  14. }
  15. }
  16. class Composite implements composite{
  17. childrenList: leaCon[];
  18. constructor() {
  19. this.childrenList = []
  20. }
  21. add(name:leaCon) {
  22. this.childrenList.push(name);
  23. }
  24. operation() {
  25. this.childrenList.forEach((child:any) => {
  26. child.operation();
  27. })
  28. }
  29. }
  30. const composite1 = new Composite();
  31. const composite2 = new Composite();
  32. const leaf1 = new Leaf('a');
  33. const leaf2 = new Leaf('b');
  34. const leaf3 = new Leaf('c');
  35. composite1.add(leaf1);
  36. composite1.add(composite2);
  37. composite2.add(leaf2);
  38. composite2.add(leaf3);
  39. composite1.operation();

组合模式的主要优点有:

  1. 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
  2. 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;

其主要缺点是:

  1. 设计较复杂,客户端需要花更多时间理清类之间的层次关系;
  2. 不容易限制容器中的构件;
  3. 不容易用继承的方法来增加构件的新功能;