概述
装饰模式是结构型设计模式之一,使用一种对客户透明的方式来动态拓展对象的功能,Java IO中各种流的嵌套就是装饰模式的很好体现。
装饰模式定义:动态地把一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
UML
装饰模式UMLComponent是定义一个对象接口,可以给这些对象动态地添加职责,ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的,至于ComcreateDecorator就是具体的装饰对象,祈祷给Component添加职责的功能。
在装饰模式中的各个角色
- 抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
- 具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
- 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并实现一个与抽象构件接口一致的接口。
- 具体装饰(Concrete Decorator)角色:负责给构件对象添加上附加的责任。
实例介绍
想到装饰,很容易想到一个人穿衣服,在不同的季节穿不同的衣服,比如夏天穿短裤、冬天穿毛裤,但是不管什么季节,内裤肯定是要穿的。
抽象组件Component类就可以是抽象类Person,而ConcreteComponent类就可以是具体的一个人Calvin,也是要被装饰的对象。抽象装饰类Decorator持有了Calvin的引用,并且回调了Calvin本身的一个“穿内裤”的行为,并且在具体的装饰类中,即“冬夏”两个类中,分别为主人公Calvin穿上了毛裤和短裤,为对象增加了额外的功能。代码也比较简单,如下所示。
public interface Person {
void dressed();
}
public class Calvin implements Person{
@Override
public void dressed() {
System.out.println("穿件内裤");
}
}
public abstract class PersonCloth implements Person{
private Person person;
public PersonCloth(Person person) {
this.person = person;
}
@Override
public void dressed() {
person.dressed();
}
}
public class SummerCloth extends PersonCloth {
public SummerCloth(Person person) {
super(person);
}
@Override
public void dressed() {
super.dressed();
System.out.println("穿件短裤");
}
}
public class WinterCloth extends PersonCloth {
public WinterCloth(Person person) {
super(person);
}
@Override
public void dressed() {
super.dressed();
System.out.println("穿条毛裤");
}
}
客户端测试类
public class DecoratorTest {
public static void main(String[] args) {
Person calvin = new Calvin();
PersonCloth sumerCloth = new SummerCloth(calvin);
PersonCloth winterCloth = new WinterCloth(calvin);
sumerCloth.dressed();
System.out.println("------------------------");
winterCloth.dressed();
}
}
运行结果:
穿件内裤
穿件短裤
------------------------
穿件内裤
穿条毛裤
总结
装饰模式动态地给一个对象添加一些额外的功能,相对于继承的方式,更加灵活。
装饰模式经常被误认为是代理模式。装饰模式是以对客户透明的方式扩展对象的功能,是继承关系的一个替代方案。而代理模式则是给一个对象提供一个代理对象,并由代理对象来控制原有对象的引用。
前者重在增加功能,后者重在对代理对象施加控制,不是对对象本身功能的增强。
网友评论