前言
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。
原理
UML类图
1、Component,抽象构件。Component是一个接口或者抽象类,是定义我们最核心的对象,也可以说是最原始的对象,比如上面的肉夹馍。
2、ConcreteComponent,具体构件,或者基础构件。ConcreteComponent是最核心、最原始、最基本的接口或抽象类Component的实现,可以单独用,也可将其进行装饰,比如上面的简单肉夹馍。
3、Decorator,装饰角色。一般是一个抽象类,继承自或实现Component,在它的属性里面有一个变量指向Component抽象构件,我觉得这是装饰器最关键的地方。
4、ConcreteDecorator,具体装饰角色。ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,它们可以把基础构件装饰成新的东西,比如把一个普通肉夹馍装饰成鸡蛋里脊肉夹馍。
实例代码
先创建抽象构件,如以下代码所示:
public interface Apple {
/**
* 描述
*/
void res();
}
创建具体构件类,如以下代码所示:
public class ConcreteApple implements Apple {
@Override
public void res() {
System.out.println("普通的苹果");
}
}
创建抽象装饰类,如以下代码所示:
public abstract class Decorator implements Apple {
// 被装饰的对象
protected Apple apple;
public Decorator(Apple apple) {
super();
this.apple = apple;
}
// 覆盖对象的方法
@Override
public void res() {
apple.res();
}
}
创建具体装饰类,如以下代码所示:
public class ConcreteDecoratorA extends Decorator{
public ConcreteDecoratorA(Apple apple) {
super(apple);
}
// 扩展的功能
public void resA(){
System.out.println("被装饰器A扩展的功能");
}
// 执行原有的函数
@Override
public void res(){
System.out.println("装饰器A=>装饰成红色的");
super.res();
System.out.println("装饰器A=>装饰结束");
}
}
public class ConcreteDecoratorB extends Decorator{
public ConcreteDecoratorB(Apple apple) {
super(apple);
}
public void resB(){
System.out.println("被装饰器B扩展的功能");
}
@Override
public void res(){
System.out.println("装饰器B=>装饰成绿色的");
super.res();
System.out.println("装饰器B=>装饰结束");
}
}
测试代码:
public class DecoratorTest {
public static void main(String[] args) {
Apple apple =new ConcreteApple();
System.out.println("-----------未装饰-------------------\n");
apple.res(); //原来的方法
System.out.println("------------------------------------\n");
decorateApple(apple) ;
}
private static void decorateApple(Apple apple){
ConcreteDecoratorB decoratorB = new ConcreteDecoratorB(apple);
System.out.println("\n-----------装饰后-------------------\n");
decoratorB.res();
System.out.println("------------------------------");
}
}
与适配器的区别
装饰器与适配器都有一个别名叫做 包装模式(Wrapper),它们看似都是起到包装一个类或对象的作用,但是使用它们的目的很不一一样。适配器模式的意义是要将一个接口转变成另一个接口,它的目的是通过改变接口来达到重复使用的目的。
而装饰器模式不是要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能,或者改变原有对象的处理方式而提升性能。所以这两个模式设计的目的是不同的。