适用情况:在不影响其他对象的情况下,以动态、透明的方式给单个对象增加职责。
需要动态地给对象增加功能,这些功能也可以动态地被撤销。
实际应用:装饰模式经常会用在数据加密,给图形界面增加边框,滚动等新特性等领域中。
之所以第二个设计模式就复习这个,在于学习设计模式时,由于时间有限,同时促进教学相长,老师要求我们同学组成小组,每小组派一个人来讲一个设计模式,于是我选择了装饰模式来讲。
装饰模式是一种用于替代继承的技术,它通过无需定义子类的方式来给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系。
定义:动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类更加灵活。
装饰模式结构图(来源于刘伟主编设计模式书的相关PPT)
代码段:
Component:
package com.decoratorpatter.hing; public interface Transform { public void move(); }
ConcreteComponent:
package com.decoratorpatter.hing; public class Car implements Transform { public void move() { System.out.println("变形金刚在陆地上移动"); } }
Decorator:
package com.decoratorpatter.hing; public class Changer implements Transform { private Transform transform; public void move() { // TODO Auto-generated method stub transform.move(); } public Changer(Transform transform) { this.transform=transform; } }
ConcreteDecoratorA:
package com.decoratorpatter.hing; public class Robot extends Changer { public Robot(Transform transform) { super(transform); System.out.println("变成机器人!"); // TODO Auto-generated constructor stub } public void say() { System.out.println("说话:我要上五环"); } }
ConcreteDecoratorB:
package com.decoratorpatter.hing; public class Airplane extends Changer { public Airplane(Transform transform) { super(transform); System.out.println("变成飞机!"); // TODO Auto-generated constructor stub } public void fly() { System.out.println("上天?哼,我这不是上来了吗!"); } }
Client:
package com.decoratorpatter.hing; public class Client { public static void main(String args[]) { Transform car=new Car(); car.move(); Robot robot=new Robot(car); robot.say(); Airplane ap=new Airplane(car); ap.fly(); } }
总结:装饰模式虽然可以动态地为对象增加新的行为,但仔细回顾不难发现,如果增加的功能需要足够多时,就难免会有修饰类对象不断产生地过程,这样系统就会显得比较庞大。所以说,每一种设计模式的使用都需要根据具体需要去选择。
后记:
透明装饰模式和半透明装饰模式:
透明装饰模式中,要求客户端完全针对抽象编程,装饰模式的透明性要求客户端程序不应该声明具体构件类型和具体装饰类型,而应该全部声明为抽象构件类型。(在实际开发中难以找到,因为装饰模式的用意时在不改变接口的前提下,增强原有类的功能。在增强功能时用户往往需要创建新的方法,如变形金刚本身是一辆车,不能说话,但是机器人可以,这就意味着机器人应该增加一个新的方法say()).
实际上,大多数装饰模式都是半透明的装饰模式,而不是完全透明的。即允许用户在客户端声明具体装饰类的对象,调用在具体装饰者中的新增的方法。