装饰者模式 Decorator:不改变原类,不使用继承,创建一个包装对象,动态地扩展原对象的功能。
优点:
- 扩展性好
- 灵活性比使用继承好
缺点:很多的装饰类可能使程序变得复杂。
类图如下:
装饰者模式 Decorator 包括四个角色:
抽象被装饰者(Component):定义一个抽象的被装饰者。
具体被装饰者(Concrete Component):定义一个具体的被装饰者。
抽象装饰者(Decorator):持有一个被装饰者(Component)对象的引用,并定义一致的接口。
-
具体装饰者(Concrete Decorator):负责具体的实现。
例如:
- 抽象被装饰者(Component)可以是人
Person
,包括两个方法eat()
drink()
abstract class Person {
abstract void eat();
abstract void drink();
}
- 具体被装饰者(Concrete Component)可以是年轻人
Teenager
,实现具体的方法eat()
drink()
class Teenager extends Person {
public void eat() {
System.out.println("teenager eat more");
}
public void drink() {
System.out.println("teenager drink more");
}
}
- 抽象装饰者(Decorator)可以是穿了衣服
ClothDecorator
,维护了一个Person
对象的引用
abstract class ClothDecorator extends Person {
public Person p;
abstract void eat();
abstract void drink();
}
- 具体装饰者(Concrete Decorator)可以是穿了 TShirt
class TShirtDecorator extends ClothDecorator {
public TShirtDecorator(Person p) {
this.p = p;
}
public void eat() {
// 预处理
p.eat();
// 后处理
}
public void drink() {
// 预处理
p.drink();
// 后处理
}
}
使用方式:
public static void main(String[] args) {
TShirtDecorator d = new TShirtDecorator(new Teenager());
d.eat();
d.drink();
}
使用实例:Java IO 中的继承方式
与上述的类图相对应:
使用方式:
使用 BufferedInputStream
来装饰 FileInputStream
:
public static void main(String[] args) {
BufferedInputStream bin = new BufferedInputStream(new FileInputStream("a.txt"));
bin.read();
}