装饰器模式的定义:指在不改变原有对象的基础上,动态地给该对象增加一些额外的功能的模式,属于对象结构型模式。
装饰器模式的核心在于类的扩展,通过装饰器模式可以透明且动态的扩展类的功能。
装饰器模式的结构:装饰器模式主要包含以下4个角色。
- 抽象构件(Component)角色:定义了被装饰对象的行为,可以是接口或抽象类。
- 具体构件(ConcreteComponent)角色:被装饰对象,抽象构件的具体实现类。
- 抽象装饰(Decorator)角色:继承或实现抽象构件,并包含被装饰对象,可以通过其子类扩展被装饰对象的功能。
- 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给被装饰对象添加附加的功能。
装饰器模式的通用实现:
//抽象构件
public interface Component {
void doingSomeThing();
}
//具体构件
public class ConcreteComponent implements Component{
@Override
public void doingSomeThing() {
System.out.println("调用具体构件做些事情!!!");
}
}
//抽象装饰类
public class Decorator implements Component{
private Component component;
public Decorator(Component component){
this.component = component;
}
@Override
public void doingSomeThing() {
component.doingSomeThing();
}
}
//具体装饰类
public class ConcreteDecorator extends Decorator{
public ConcreteDecorator(Component component) {
super(component);
}
@Override
public void doingSomeThing() {
super.doingSomeThing();
addExtend();
}
private void addExtend() {
System.out.println("使用具体装饰器增加扩展功能!!!");
}
}
//测试类
public class DecoratorTest {
public static void main(String[] args) {
Component component = new ConcreteComponent();
component.doingSomeThing();
Component decorator = new ConcreteDecorator(component);
decorator.doingSomeThing();
}
}
装饰器模式的结构图:
装饰器模式的应用:
曾经看过动画《数码宝贝》的都知道数码宝贝可以变身,那么我们就用装饰器模式来实现动画中亚古兽的变身,亚古兽可以变身为暴龙兽,再变身为机械暴龙兽。其中亚古兽就是被装饰对象,暴龙兽和机械暴龙兽就是装饰后的对象,这些都可用装饰器模式来实现。
//抽象构件:亚古兽
public interface IAgumon {
void display();
}
//具体构件:亚古兽
public class Agumon implements IAgumon{
@Override
public void display() {
System.out.println("我是亚古兽!!!");
System.out.println("技能:小型火焰!!!");
}
}
//抽象装饰类
public class Changer implements IAgumon{
private IAgumon agumon;
public Changer(IAgumon agumon){
this.agumon = agumon;
}
@Override
public void display() {
agumon.display();
}
}
//具体装饰类:暴龙兽
public class Greymon extends Changer{
public Greymon(IAgumon agumon) {
super(agumon);
}
@Override
public void display() {
super.display();
System.out.println("亚古兽进化--->暴龙兽");
System.out.println("技能:超级火焰!!!");
}
}
//具体装饰类:机械暴龙兽
public class MetalGreymon extends Changer{
public MetalGreymon(IAgumon agumon) {
super(agumon);
}
@Override
public void display() {
super.display();
System.out.println("暴龙兽进化--->机械暴龙兽");
System.out.println("技能:究极破坏炮!!!");
}
}
//测试类
public class AgumonChangeTest {
public static void main(String[] args) {
IAgumon agumon = new Agumon();
IAgumon greymon = new Greymon(agumon);
greymon.display();
System.out.println("-----------------分割线-----------------------");
IAgumon metalGreymon = new MetalGreymon(greymon);
metalGreymon.display();
}
}
亚古兽进化应用场景的类图:
装饰器模式的优点:
- 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用。
- 通过使用不同装饰类及这些装饰类的排列组合,可以实现不同效果。
- 装饰器模式完全遵守开闭原则
装饰器模式的缺点:装饰器模式会增加许多子类,过度使用会增加程序得复杂性。
装饰器模式的使用场景:
- 当需要扩展一个类或给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。
- 用于通过对现有的一组基本功能进行排列组合而产生非常多的功能。
- 当对象的功能需要动态地添加,也可以再动态地撤销时,可以使用装饰器模式。
装饰器模式的扩展:装饰器模式所包含的 4 个角色不一定都要存在,在有些应用环境下模式可以简化,例如以下两种情况。
- 如果只有一个具体构件而没有抽象构件时,可以让抽象装饰继承具体构件。
- 如果只有一个具体装饰时,可以将抽象装饰和具体装饰合并。
装饰器模式在源码中的应用:装饰器模式在JDK中的最明显的应用就是Java I/O类库的设计。
装饰器模式和代理模式的区别:装饰器模式强调自身功能的扩展,代理模式强调对代理过程的控制。