装饰器模式是指允许对一个现有的对象加入其它额外的功能并且不改变其原来的结构,属于结构型模式。这种模式通常会创建一个装饰类来包装原有的类以达到装饰的效果。以下举一个电脑配置的例子说明。
首先创建一个电脑的接口,给出两个抽象方法,分别是获取名字和获取价格:
/** * 抽象电脑类 * @author 樱桃肉丸子 */ public interface AbstractComputer { String name(); double price(); }
创建一个普通电脑类实现上面的接口:
/** * 普通电脑类 * @author 樱桃肉丸子 */ public class Computer implements AbstractComputer { @Override public String name() { return "普通电脑"; } @Override public double price() { return 3000; } }
现在有一个需求就是需要给这台普通的电脑加一个内存或是加一个硬盘,即在现有的基础上对该电脑进行装饰。
首先需要创建一个装饰类接口来确定加入的是哪种配置,这样逻辑上是说得通的,电脑配件依附于电脑,和电脑有相同的属性。
/** * 装饰类接口 * @author 樱桃肉丸子 */ public interface Device extends AbstractComputer { String name(); double price(); }
分别创建装饰类的实现类来定义具体装饰内容:
/** * 内存类 * @author 樱桃肉丸子 */ public class Memory implements Device { public AbstractComputer computer; public Memory(AbstractComputer computer) { this.computer = computer; } @Override public String name() { return computer.name()+"加内存"; } @Override public double price() { return computer.price()+300; } }
/** * 硬盘类 * @author 樱桃肉丸子 */ public class HardDisk implements Device { public AbstractComputer computer; public HardDisk(AbstractComputer computer) { this.computer = computer; } @Override public String name() { return computer.name()+"加硬盘"; } @Override public double price() { return computer.price()+500; } }
最后写一个demo来看一下装饰效果如何:
public class DecoratorPatternDemo { public static void main(String[] args) { //创建普通的电脑 Computer computer = new Computer(); //给普通电脑加硬盘 HardDisk hardDisk = new HardDisk(computer); System.out.println(hardDisk.name()); System.out.println(hardDisk.price()); //给普通电脑加内存 Memory memory = new Memory(computer); System.out.println(memory.name()); System.out.println(memory.price()); //给普通电脑加硬盘和内存 Memory memory1 = new Memory(hardDisk); System.out.println(memory1.name()); System.out.println(memory1.price()); } }
输出结果:
总结:
装饰器的价值就体现在“装饰”上,他只是装饰,并不会改变原来对象的性质。当然,以上功能也可以通过继承实现,但当一个对象出现一个新的功能就要创建一个子类这样是不合理的。装饰器模式动态添加功能大大提高了拓展性,一定程度上降低了子类的数量,降低了耦合度。