先给出一个情景:开发一个给人搭配不同服饰的系统

我们要考虑的

  • 满足开放封闭原则 - 不能每添加一种服饰就要做大量的修改
  • 组装过程最好在类的内部,对外不可见
  • 需要考虑组装的顺序

装饰模式UML图

avatar
如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类

针对模式原型的代码实现(Java)

Component接口

1
2
3
public interface Component {
public abstract void Operation();
}

Component实现类

1
2
3
4
5
6
public class ConceteComponent implements Component {
@Override
public void Operation() {
System.out.println("具体对象的操作");
}
}

具体Component类

1
2
3
4
5
6
7
8
public class ConcreteDecoratorA extends Decorator {

@Override
public void Operation() {
super.Operation();
System.out.println("具体装饰对象A的操作");
}
}
1
2
3
4
5
6
7
8
public class ConcreteDecoratorB extends Decorator {

@Override
public void Operation() {
super.Operation();
System.out.println("具体装饰对象B的操作");
}
}

装饰类

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Decorator implements Component {
protected Component component;
public void SetComponent(Component component) {
this.component = component;
}

@Override
public void Operation() {
if (component != null) {
component.Operation();
}
}
}

客户端

1
2
3
4
5
6
7
8
public static void main(String[] args) {
ConceteComponent c = new ConceteComponent();
ConcreteDecoratorA d1 = new ConcreteDecoratorA();
ConcreteDecoratorB d2 = new ConcreteDecoratorB();
d1.SetComponent(c);
d2.SetComponent(d1);
d2.Operation();
}

针对情景的代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
// 等价ConcreteComponent
public class Person {
public Person () {} // 无参构造函数

private String name;
public Person(String name) { // 含参构造函数
this.name = name;
}

public void show() {
System.out.println("装扮人是" + name);
}
}

衣服类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 等价于Decorator
public class Finery extends Person {
protected Person component;
public void decorate(Person component) {
this.component = component;
}

@Override
public void show() {
if (component != null) {
component.show();
}
}
}

具体衣服类

1
2
3
4
5
6
7
8
// 等价于ConcreteDecorator
public class Trouser extends Finery {
@Override
public void show() {
System.out.println("垮裤");
super.show();
}
}
1
2
3
4
5
6
7
8
// 等价于ConcreteDecorator
public class TShirts extends Finery {
@Override
public void show() {
System.out.println("T恤");
super.show();
}
}

客户端

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
Person xyy = new Person("xyy");

TShirts tShirts = new TShirts();
Trouser trouser = new Trouser();

tShirts.decorate(xyy);
trouser.decorate(tShirts);
trouser.show();
}

装扮模式的优势

动态地给一个对象添加一些额外地职责

  1. 将对象地实现和对象的使用分开 - 每个装饰对象只关心自己的功能,不需关心如何被添加到对象链中
  2. 为已有功能动态地添加更多功能
  3. 特定情况特殊行为 - 新加入地功能满足在某种特定情况才会执行的特殊行为

装饰模式的缺点

  1. 虽然扩展性较高,但是类的数量较多(若需求明确且后期发生变化概率不大,则没必要使用装饰模式)
  2. 很难知晓类被装饰了多少层

本文部分内容改编于程杰老师的《大话设计模式》