文章目录
  1. 1. 模式定义
  2. 2. 模式结构
  3. 3. UML图
  4. 4. 代码实现
    1. 4.1. TheGreatestSage.java
    2. 4.2. Monkey.java
    3. 4.3. Change.java
    4. 4.4. Bird.java
    5. 4.5. Fish.java
    6. 4.6. 测试类
    7. 4.7. 运行结果
  5. 5. 模式分析
  6. 6. 装饰模式的优点
  7. 7. 装饰模式的缺点

今天我们来学习另一种结构型模式,它就是装饰模式(Decorator Pattern)。

模式定义

动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。

模式结构

装饰模式包含如下角色:

Component: 抽象构件
ConcreteComponent: 具体构件
Decorator: 抽象装饰类
ConcreteDecorator: 具体装饰类

UML图

代码实现

孙悟空有七十二般变化,他的每一种变化都给他带来一种附加的本领。他变成鱼儿时,就可以到水里游泳;他变成鸟儿时,就可以在天上飞行。

本例中,Component的角色便由鼎鼎大名的齐天大圣扮演;ConcreteComponent的角色属于大圣的本尊,就是猢狲本人;Decorator的角色由大圣的七十二变扮演。而ConcreteDecorator的角色便是鱼儿、鸟儿等七十二般变化。

TheGreatestSage.java

1
2
3
4
5

public interface TheGreatestSage {

public void move();
}

Monkey.java

1
2
3
4
5
6
7
8
9
10
11
/**
* 具体构件
*/
public class Monkey implements TheGreatestSage {

@Override
public void move() {
//代码
System.out.println("Monkey Move");
}
}

Change.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

/**
* 抽象装饰类
*/
public class Change implements TheGreatestSage {
private TheGreatestSage sage;

public Change(TheGreatestSage sage){
this.sage = sage;
}

@Override
public void move() {
// 代码
sage.move();
}

}

Bird.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 具体装饰类
*/
public class Bird extends Change {

public Bird(TheGreatestSage sage) {
super(sage);
}

@Override
public void move() {
System.out.println("Bird Move");
}

public void fly() {
System.out.println("Bird fly");
}
}

Fish.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

/**
* 具体装饰类
*/
public class Fish extends Change {

public Fish(TheGreatestSage sage) {
super(sage);
}

@Override
public void move() {
System.out.println("Fish Move");
}

public void swim() {
System.out.println("Fish swim");
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

public class MyClass {
public static void main(String[] args) {
TheGreatestSage sage = new Monkey();
//孙悟空变成一只鸟
Bird bird = new Bird(sage);
bird.move();
bird.fly();

//孙悟空变成一只鱼
Fish fish = new Fish(sage);
fish.move();
fish.swim();
}
}

运行结果

模式分析

  • 与继承关系相比,关联关系的主要优势在于不会破坏类的封装性,而且继承是一种耦合度较大的静态关系,无法在程序运行时动态扩展。在软件开发阶段,关联关系虽然不会比继承关系减少编码量,但是到了软件维护阶段,由于关联关系使系统具有较好的松耦合性,因此使得系统更加容易维护。当然,关联关系的缺点是比继承关系要创建更多的对象。

  • 使用装饰模式来实现扩展比继承更加灵活,它以对客户透明的方式动态地给一个对象附加更多的责任。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。

装饰模式的优点

  • 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
    可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为。

  • 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。

  • 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。

装饰模式的缺点

  • 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,同时还将产生很多具体装饰类。这些装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度。

  • 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

代码已经放到GitHub上了https://github.com/HJXANDHMR/DesignPattern

参考
http://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/decorator.html

欢迎大家关注我的微信公众号,我会不定期的分享些Android开发的技巧

文章目录
  1. 1. 模式定义
  2. 2. 模式结构
  3. 3. UML图
  4. 4. 代码实现
    1. 4.1. TheGreatestSage.java
    2. 4.2. Monkey.java
    3. 4.3. Change.java
    4. 4.4. Bird.java
    5. 4.5. Fish.java
    6. 4.6. 测试类
    7. 4.7. 运行结果
  5. 5. 模式分析
  6. 6. 装饰模式的优点
  7. 7. 装饰模式的缺点