- 装饰模式职责:
— 动态地为一个对象增加新的功能。
— 装饰模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
- 实现细节:
— Component 抽象构件角色
真实对象和装饰对象有相同的接口。这样,客户对象就能够以与真实对象相同的方式同装饰对象交互。
— ConcreteComponent 具体构件角色(真实对象)
I
O流中的FileInputStream、FileOutputStream
— Decorator 装饰角色
持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象。这样就能在真实对象调用前后增加新的功能。
— ConcreteDecorator 具体装饰角色
负责给构件对象增加新的责任。
关系类图如下:
- 开发中使用的场景:
— IO中输入流和输出流的设计
— Swing包中图形界面构件功能
— Servlet API中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,增强了request对象的功能。
— Struts2中,request,response,session对象的处理。
实现例子:
/**
* Component 抽象构件角色
*/
public interface ICar {
void move();
}
/**
* ConcreteComponent 具体构件角色(真实对象)
*/
class Car implements ICar{
public void move() {
System.out.println("陆地上跑!");
}
}
//Decorator 装饰角色
class SuperCar implements ICar{
protected ICar car;
SuperCar(ICar car){
this.car = car;
}
public void move() {
car.move();
}
}
//ConcreteDecorator 具体装饰角色
class FlyCar extends SuperCar{
FlyCar(ICar car){
super(car);
this.car = car;
}
public void move() {
super.move();
fly();
}
void fly(){
System.out.println("天上飞!");
}
}
//ConcreteDecorator 具体装饰角色
class SwimCar extends SuperCar{
SwimCar(ICar car){
super(car);
this.car = car;
}
public void move() {
super.move();
swim();
}
void swim(){
System.out.println("水里游!");
}
}
//ConcreteDecorator 具体装饰角色
class AICar extends SuperCar{
AICar(ICar car){
super(car);
this.car = car;
}
public void move() {
super.move();
autoDrive();
}
void autoDrive(){
System.out.println("自动驾驶!");
}
}
public class Client {
public static void main(String[] args){
Car car = new Car();//真实角色
car.move();
System.out.println("1.------装饰Car,为car增加新的功能,飞行--------");
FlyCar flycar = new FlyCar(car);
flycar.move();
System.out.println("2.------装饰Car,为car增加新的功能,水里游--------");
SwimCar swimcar = new SwimCar(car);
swimcar.move();
System.out.println("3.------装饰Car,为car增加两个新的功能,飞行,水里游--------");
SwimCar swimcar2 = new SwimCar(new FlyCar(car));
swimcar2.move();
}
}
运行结果:
例子的类图如下:
- 总结
— 装饰模式(Decorator)也叫包装模式(Wrapper)。
— 装饰模式降低系统的耦合度,可以动态地增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。
- 优点
— 扩展对象功能,比继承灵活,不会导致类个数急剧增加
— 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象。
— 具体构件和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类。
- 缺点
— 产生很多小对象。大量小对象占据内存,一定程度上影响性能。
— 装饰模式易于出错,调试排查比较麻烦。
- 装饰模式和桥接模式的区别
两个模式都是为了解决过多子类对象问题。但他们诱因不一样。桥接模式是对象自身现有机制沿着多维度变化。装饰模式是为了增加新的功能。