设计模式十八之装饰模式

通过理论,代码示例,Android源码来学习装饰模式

介绍

装饰模式 (也称为 Decorator Pattern) 也称为包装模式,属于结构型模式之一,其使用一种对客户端透明的方式来动态的扩展对象的功能,同时它也是继承关系的一种替代方案之一。在现实生活中你也看见很多装饰模式的例子,或者可以大胆地说装饰模式无处不在,就拿人来说,人需要各式各样的衣着,不管你穿着怎么,但是,对于个人的本质来说是不变的,充其量只是在外面披上一层 “遮羞物” 而已,这就是装饰模式。

定义

动态的给一个对象田爱军一些额外的职责。就是增加功能来说,装饰模式生成子类更为灵活。

使用场景

需要透明且动态地扩展类的功能时。

UML 类图

  • Component: 抽象组件,可以试一个接口或者抽象类,其充当的就是被装饰的原始对象。
  • ConcreteComponent: 组件具体实现类,该类是 Component 类的基本实现,也是我们装饰的具体对象。
  • Decorator: 抽象装饰者。
  • ConcreteDecorator: 装饰者具体实现类

代码示例

业务背景: 为 boy 穿衣

定义一个抽象的穿衣行为:

1
2
3
4
5
6
7
public abstract class Person {

/**
* Person 下有一个穿着的抽象方法
*/
public abstract void dressed();
}

声明一个具体行为实现:

1
2
3
4
5
6
public class Boy extends Person {
@Override
public void dressed() {
System.out.println("男孩穿着内裤");
}
}

定义一个用来装饰具体行为的抽象:

1
2
3
4
5
6
7
8
9
10
11
12
13
public abstract class PersonCloth extends Person {
protected Person person
;

public PersonCloth(Person person) {
this.person = person;
}

@Override
public void dressed() {
person.dressed();
}
}

具体装饰实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class ExpensiveCloth extends PersonCloth {
public ExpensiveCloth(Person person) {
super(person);
}

@Override
public void dressed() {
super.dressed();
//穿短袖
dressShirt();
//穿皮衣
dressLeather();
//穿牛仔裤
dressJean();
}

private void dressShirt() {
System.out.println("穿上短袖");
}

private void dressLeather() {
System.out.println("穿上皮衣");
}

private void dressJean() {
System.out.println("穿上牛仔裤");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class CheapCloth extends PersonCloth {
public CheapCloth(Person person) {
super(person);
}

@Override
public void dressed() {
super.dressed();
dressShorts();
}

private void dressShorts() {
System.out.println("穿条短裤");
}
}

test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void testDecorator(){
//首先得有一个男孩
Person person = new Boy();

//先穿上便宜的衣服
PersonCloth cheapCloth = new CheapCloth(person);
cheapCloth.dressed();

//或者在穿上有点档次的衣服
PersonCloth personCloth = new ExpensiveCloth(person);
personCloth.dressed();

}

output:

1
2
3
4
5
6
7
男孩穿着内裤
穿条短裤

男孩穿着内裤
穿上短袖
穿上皮衣
穿上牛仔裤

总结

装饰模式和我们前面讲的 代理模式 有点类似,有时候甚至容易混淆,倒不是说会把代理当成装饰,而是常常会是将装饰看作代理,装饰模式是以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案;而代理模式则是给一个对象提供一个代理对象,并有代理对象来控制对原有的对象的引用。装饰模式应该为所装饰的对象增强功能;代理模式对代理的对象施加控制,但不对对象本身的功能进行增强。

坚持原创技术分享,您的支持将鼓励我继续创作!