浅谈设计模式(二):装饰器模式|中介模式|原型模式

  • 2020 年 2 月 11 日
  • 筆記

装饰器模式(Decorator Pattern)

装饰器模式可用来给一个类动态添加功能,将其装饰成一个新的类。这就是装饰器的概念。看到这里我们可能会想,要达到这种效果,我们用子类继承父类不就可以了吗? 没错装饰器模式,本身是一种继承的替代方案。那既然是替代方案,那么自然就有它不一样的地方。

具体区别在哪里呢? 请看

  • 装饰器模式更灵活:继承时父子类的关系是静态的,而装饰器模式是动态的,装饰类和被装饰类的关系是运行时候确认的
  • 装饰类和被装饰类的耦合关系是松散的,各自可以独立变化

下面看看具体的代码。具体过程可看注释

// 1.首先我们有一个Pen接口  public interface Pen {    public void write();  }  // 2.Pencil类实现了Pen这个接口  public class Pencil implements Pen {      public void write () {          System.out.print("写");      }  }  // 3.装饰类PencilDecorator也实现了Pen这个接口,且代理调用Pencil的方法  public class PencilDecorator implements Pen{      Pen pen;      public PencilDecorator(Pen pen) {        this.pen = pen;      }      public void write () {        pen.write();      }  }  // 4.用具体装饰类继承PencilDecorator,这样就可以做扩展变化  public class BluePencilDecorator extends PencilDecorator{      public BluePencilDecorator (Pen pen) {          super(pen);      }      public void writeBlue () {          this.write();          System.out.println("写出来是蓝色的");      }  }  // 同4.用具体装饰类继承PencilDecorator,这样就可以做扩展变化  public class RedPencilDecorator extends PencilDecorator{      public RedPencilDecorator (Pen pen) {          super(pen);      }      public void writeRed () {          this.write();          System.out.println("写出来是红色的");      }  }  // 测试  public class Test {      public static void main(String args []) {         Pen pencil = new Pencil();         RedPencilDecorator redPencil = new RedPencilDecorator(pencil);         BluePencilDecorator bluePencil = new BluePencilDecorator(pencil);         redPencil.writeRed();         bluePencil.writeBlue();      }  }

输出结果

代码的结构如下图所示

从这里我们看到了,经过PencilDecorator类这一层的隔离,Pencil类和BluePencilDecorator类/RedPencilDecorator类在一定程度上解耦,从而各自独立发展了。这就是代理模式能够替代继承的原因和它的独特优势

唉!! 等一下,好像看到了什么熟悉的东西,请看

没错,这还真就是代理模式的代码。

在这里,我们可以从两个角度去理解装饰器模式。

  • 第一,从构成上看,装饰器模式 = 代理模式 + 类继承。 也就是在代理模式的基础上,加了一堆继承[代理类]的子类,从而进行扩展变化,并且还尽量减少了和原有类的联系。
  • 第二,从功能上看,代理模式侧重的是“控制”,而装饰器模式侧重的是“扩展”。比如说,类A代理了类B,那么这两个类由于同一个接口的约束,它们的方法和实现的功能其实是一样的。而类C装饰了类D,那么这个时候类C不仅仅具备了类D的方法,同时还能加入自己的特殊逻辑。

中介者模式(Mediator Pattern)

简单的说,中介者模式是一个分散到集中的一个过程

还是看下具体的代码

// Colleague接口  public interface Colleague {      public void handleExternal(Mediator mediator);      public void handleInternal();  }  // 中介者接口  public abstract class Mediator {     public Colleague A;     public Colleague B;     public Colleague C;     public Mediator (Colleague A, Colleague B, Colleague C) {         super();      this.A = A;      this.B = B;      this.C = C;    }    public abstract void handleA ();    public abstract void handleB ();    public abstract void handleC ();  }  // 实现了中介者接口的中介者类,封装了不同Colleague类的对象间的复杂操作  public class ConcreteMediator extends Mediator{      public ConcreteMediator(Colleague A, Colleague B, Colleague C) {          super(A,B,C);      }      public void handleA() {          B.handleInternal();          C.handleInternal();      }      public void handleB() {        A.handleInternal();        C.handleInternal();      }      public void handleC() {        A.handleInternal();        B.handleInternal();      }  }  // Colleague类在涉及其他Colleague类的复杂操作的时候,通过中介者调用  public class A implements Colleague {      public void handleExternal(Mediator mediator) {        mediator.handleA();        System.out.println("---------------");      }      public void handleInternal() {          System.out.println("A");      }  }  // Colleague类在涉及其他Colleague类的复杂操作的时候,通过中介者调用  public class B implements Colleague {      public void handleExternal(Mediator mediator) {          mediator.handleB();          System.out.println("---------------");      }      public void handleInternal() {          System.out.println("B");      }  }  // Colleague类在涉及其他Colleague类的复杂操作的时候,通过中介者调用  public class C implements Colleague {      public void handleExternal(Mediator mediator) {          mediator.handleC();          System.out.println("---------------");      }        public void handleInternal() {          System.out.println("C");      }  }  // 测试  public class main {      public static void main(String args []) {          Colleague a = new A();          Colleague b = new B();          Colleague c = new C();          Mediator mediator = new ConcreteMediator(a,b,c);          a.handleExternal(mediator);          b.handleExternal(mediator);          c.handleExternal(mediator);      }  }

结果输出

中介者模式理解起来,就好像

  1. 你有很多杂乱的物品摆放在房间的不同地方,找起来很不好找,现在把这些物品统一放到一个柜子里,方便集中管理。
  2. 一群人去食堂打饭的时候,如果各自去取菜那么食堂可能乱做一团,所以这时候食堂大妈就成为了“中介者”

原型模式(Prototype Pattern)

原型模式是什么?

一句话,原型模式就是克隆对象,完了。

这么简单? 这也能叫设计模式?

没错,就是这样

让我们看下代码

// 通过实现Cloneable接口并重写clone方法的方式,让Bar对象变得可克隆。  public class Bar implements Cloneable {      String value;      public String getValue () {        return value;      }      public void setValue (String value) {          this.value = value;      }      public Bar clone() {          Bar clone = null;          try {              clone = (Bar)super.clone();          } catch (CloneNotSupportedException e) {              e.printStackTrace();          }          return clone;      }  }  // 调用clone方法可以克隆对象  public class mian {      public static void main(String args []) {        Bar bar = new Bar();        Bar bar2 = bar.clone();        bar.setValue("1");        bar2.setValue("2");        System.out.println(bar.getValue());        System.out.println(bar2.getValue());      }  }

运行结果

告诉我,原型模式的本质是什么

原型模式的本质就是—— 套娃

原型模式的优缺点

  • 原型模式的优点: 底层的二进制实现拷贝,相比起new操作可以节约性能
  • 原型模式的缺点: 构造函数没有调用,牺牲了灵活性