4

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

 3 years ago
source link: https://zhuanlan.zhihu.com/p/100351713
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

广发证券 技术工程师

装饰器模式(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操作可以节约性能
  • 原型模式的缺点: 构造函数没有调用,牺牲了灵活性

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK