装饰器模式又叫包装器模式,用于动态的给一个对象增加一些额外的职能,取代一些情况下的继承的使用,增加灵活性。
装饰器模式主要有一下部分组成:
1)
抽象构件角色(
Component
):定义一个抽象接口,以规范准备接收附加责任的对象。
2)
具体构件角色
(Concrete Component)
:这是被装饰者,定义一个将要被装饰增加功能的
类。
3)
装饰角色
(Decorator)
:持有一个构件对象的实例,并定义了抽象构件定义的接口。
4)
具体装饰角色
(Concrete Decorator)
:负责给构件添加增加的功能。
应用的场景类似于:你的电脑内存只有2G,但是你想有一台内存是4G的电脑,你是选择加根内存条,还是买一台4G的电脑。又如果你的电脑没有无线网卡,你想有一台有无线网卡的电脑,你是去买个无线网卡插上,还是去买台有无线网卡的电脑。如果你的选择是买,那么当你在出现多个需求的时候,你可能买了很多台电脑了,明显这是没有必要的。你只需要的缺什么就往原来的电脑上加什么就可以了(当然是在兼容的情况下)。这就类似于一类的东西需要添加一个属性或功能,你是选择继承产生新的子类还是选择装饰器模式添加新的功能。
下面的例子演示这种情况。
1 package com.cnblogs.ipolaris.Decorator.test; 2 3 public interface Computer { 4 public void say(); 5 public void describe(); 6 }
1 package com.cnblogs.ipolaris.Decorator.test; 2 3 public class CommonComputer implements Computer { 4 5 @Override 6 public void say() { 7 this .describe(); 8 } 9 10 @Override 11 public void describe() { 12 System. out .println("我是一台2G无网卡的电脑" ); 13 } 14 15 }
1 package com.cnblogs.ipolaris.Decorator.test; 2 3 public abstract class ComputerDecorator implements Computer { 4 5 private Computer computer ; 6 7 public ComputerDecorator(Computer computer){ 8 this .computer = computer; 9 } 10 11 public Computer getComputer() { 12 return computer ; 13 } 14 15 16 public void setComputer(Computer computer) { 17 this .computer = computer; 18 } 19 20 21 22 public abstract void say() ; 23 24 }
1 package com.cnblogs.ipolaris.Decorator.test; 2 3 public class AddMeComputer extends ComputerDecorator { 4 5 public AddMeComputer(Computer computer) { 6 super (computer); 7 // TODO Auto-generated constructor stub 8 } 9 10 @Override 11 public void describe() { 12 13 System. out .println("增加了2G内存,升级为4G" ); 14 } 15 16 @Override 17 public void say() { 18 this .getComputer().say(); 19 this .describe(); 20 } 21 22 }
1 package com.cnblogs.ipolaris.Decorator.test; 2 3 public class AddWifiComputer extends ComputerDecorator { 4 5 public AddWifiComputer(Computer computer) { 6 super (computer); 7 // TODO Auto-generated constructor stub 8 } 9 10 @Override 11 public void say() { 12 this .getComputer().say(); 13 this .describe(); 14 15 } 16 17 @Override 18 public void describe() { 19 System. out .println("我增加了无线模块" ); 20 21 } 22 23 }
1 package com.cnblogs.ipolaris.Decorator.test; 2 3 public class Test { 4 5 /** 6 * @param args 7 */ 8 public static void main(String[] args) { 9 System. out .println("**************当前电脑*************" ); 10 Computer computer = new CommonComputer(); 11 computer.say(); 12 System. out .println("**************只加内存的电脑*************" ); 13 computer = new AddMeComputer(computer); 14 computer.say(); 15 System. out .println("**************加了内存后加网卡的电脑*************" ); 16 computer = new AddWifiComputer(computer); 17 computer.say(); 18 19 } 20 21 }
运行结果
**************当前电脑************* 我是一台2G无网卡的电脑 **************只加内存的电脑************* 我是一台2G无网卡的电脑 增加了2G内存,升级为4G **************加了内存后加网卡的电脑************* 我是一台2G无网卡的电脑 增加了2G内存,升级为4G 我增加了无线模块
当你想单独的添加无线模块式,只要删除
computer = new AddMeComputer(computer);
即可。
直观上来说,如果用继承,实现单独添加内存,单独添加无线模块,同时添加内存和无线模块,至少要三个子类,而这里是装饰器只要对应每个功能即可,可以以各种方式组合起来,不需要添加新的子类