装饰器模式简介
装饰器模式(Decorator Pattern) 允许向一个现有的对象添加新的功能,同时又不改变其结构,这种类型的设计模式属于结构性模式,它是现有的类的一个包装。
装饰器模式创建了一个修饰类,将对象包装在修饰类中,在保持类方法签名完整性的前提下,提供了额外的功能。
我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀,装饰器模式可以帮助我们解决这个问题。
实现方式
装饰器模式包含四个核心角色:
- 抽象组件(Component): 一个抽象接口或者类,定义了原始对象的装饰器对象,是具体组件类的父类或接口。
- 具体组件(Concrete Component): 被装饰的原始对象,定义了需要添加新功能的对象。
- 抽象装饰器(Decorator): 继承自抽象组件,包含了一个抽象组件对象,并定义了与抽象组件相同的接口,同时可以通过组合方式持有其他装饰器对象。
- 具体装饰器(Concrete Decorator): 实现了抽象装饰器,负责向抽象组件添加新的功能。通常会在调用原始对象的方法之前或之后执行自己的操作。
1、Component 类充当抽象角色,不应该具体实现。
2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。
根据一个例子来具体说明:
不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。
在这个例子中具体的组件就是一幅画,玻璃和画框都可以看作是画的装饰。
因此,首先我们来定义这幅画的抽象组件接口和具体的组件:
//抽象组件
public interface Component {
void samp();
}
//具体组件 “一幅画”
public class ConcreteComponent implements Component{
@Override
public void samp() {
System.out.println("i am an picture");
}
}
然后是抽象装饰器,可以通过继承这个类来为一幅画添加各种装饰:
在这个抽象类中引入了抽象组件对象,可以通过这种方式获得其他的装饰器对象,然后再实现自己的装饰。
//抽象装饰器
class Decorator implements Component{
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void samp() {
this.component.samp();
}
}
具体装饰角色,分别为画加画框和玻璃:
//具体装饰器A
class ConcreteDecoratorA extends Decorator{
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void samp(){
super.samp();
System.out.println("给这个picture加个画框");
}
}
//具体装饰器B
class ConcreteDecoratorB extends Decorator{
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void samp(){
super.samp();
System.out.println("给这个picture加个玻璃");
}
}
测试类:先为一幅画添加画框,再为它添加玻璃:
public static void main(String[] args) {
Component comp=new ConcreteComponent();
//给这幅画加一个画框
Component comp1=new ConcreteDecoratorA(comp);
comp1.samp();
//再给这幅画加个玻璃
System.out.println("=============================");
Component comp2=new ConcreteDecoratorB(comp1);
comp2.samp();
}
输出:
在上述例子中,这幅画是ConcreteComponent类,而画框,玻璃是装饰类,要装饰的是Component类。系统先为画添加了一个画框,又为装了画框的画添了玻璃,从而这幅画被两个装饰装饰好了。当然,还可以为它继续装饰,或者按照其他的装饰顺序进行装饰。
总结
优点:
- 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
- 通过不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出更多不同行为的组合。
缺点:
- 使用装饰模式会使用更多的类去创造对象,过多的装饰类会使程序变得复杂,可读性差。