简述
装饰模式是动态地扩展一个对象的功能,而不需要改变原始类代码的一种成熟模式。在装饰模式中,“具体组件”类和“具体装饰”类是该模式中的最重要的两个角色。
类图
装饰模式四种角色
- 抽象组件(Component)
- 具体组件(ConcreteComponent)
- 装饰(Decorator)
- 具体装饰(ConcreteDecotator)
装饰模式的优缺点
优点
- 被装饰者和装饰者是松耦合关系。由于装饰(Decorator)仅仅依赖于抽象组件(Component),因此具体装饰只知道它要装饰的对象是抽象组件的某一个子类的实例,但不需要知道是哪一个具体子类。
- 装饰模式满足“开-闭原则”。不必修改具体组件,就可以增加新的针对该具体组件的具体装饰。
- 可以使用多个具体装饰来装饰具体组件的实例。
缺点
- 装饰模式比继承更加灵活机动的特性,也同时意味着更加多的复杂性。装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出较佳选择。
案例
抽象组件
package Decorator;
/**
* 抽象组件 -- 组件
* @author hjw
*/
public abstract class Component {
/**
* 输出所有家具
* @return
*/
public abstract StringBuffer show();
}
具体组件
package Decorator;
/**
* 具体组件 -- 新家
* @author hjw
*/
public class MyNewHouse extends Component{
public static final String Component = "这是大佬的家,家里有:";
/**
* 重写父类组件方法,拼接家具字符
*/
@Override
public StringBuffer show() {
StringBuffer stringBuffer = new StringBuffer(Component);
return stringBuffer;
}
}
装饰
package Decorator;
/**
* 装饰者 -- 家具
* @author hjw
*/
public abstract class Furniture extends Component {
/**
* 组合父类属性
*/
public Component component;
/**
* 空构造
*/
public Furniture() {}
/**
* @param component
*/
public Furniture(Component component) {
this.component = component;
}
具体装饰
package Decorator;
/**
* 具体家具 -- 沙发
* @author hjw
*
*/
public class Sofa extends Furniture {
public static final StringBuffer Sofa = new StringBuffer("水晶沙发 ");
public Sofa(Component component) {
super(component);
}
public StringBuffer Sofa() {
System.out.println("买了个水晶沙发");
return Sofa;
}
@Override
public StringBuffer show() {
StringBuffer stringBuffer = component.show().append(Sofa());
System.out.println(stringBuffer);
return stringBuffer;
}
}
package Decorator;
/**
* 具体家具--电视
* @author hjw
*/
public class TV extends Furniture {
public static final StringBuffer TV = new StringBuffer("液晶电视 ");
public TV(Component component) {
super(component);
}
public StringBuffer TV() {
System.out.println("买了台液晶电视");
return TV;
}
/**
* 拼接家具字符
*/
@Override
public StringBuffer show() {
StringBuffer stringBuffer = component.show().append(TV());
System.out.println(stringBuffer);
return stringBuffer;
}
}