一、概念
装饰者模式是结构型设计模式。
装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
允许向一个现有的对象添加新的功能。同时又不改变其结构,它是作为现有的类的一个包装。
主要解决的问题: 一般我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
二、角色分析
抽象构件角色(Component):定义一个对象接口或抽象类,可以给这些对象动态地添加职责。
具体构件角色(ConcreteComponent):实际被动态地添加职责的对象。
抽象装饰者角色(Decorator):实现了Component接口,用来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。
具体装饰者角色(ConcreteDecorator):动态地添加职责的对象。
三、案例演示:
抽象构件角色(Man.java):
// 男人
public interface Man {
public void getManDesc();
}
具体构件角色(NormalMan.java):
// 普通男人
public class NormalMan implements Man{
private String name = null;
public NormalMan(String name) {
this.name = name;
}
@Override
public void getManDesc() {
System.out.print(name + ": ");
}
}
抽象装饰者角色(AttachedPropertiesDecorator.java):
// 附加属性装饰者
public abstract class AttachedPropertiesDecorator implements Man{
private Man man;
public AttachedPropertiesDecorator(Man man) {
this.man = man;
}
public void getManDesc() {
man.getManDesc();
}
}
具体装饰者角色(CarDecoratorImpl.java、HouseDecoratorImpl.java、DepositDecoratorImpl.java、QualityDecoratorImpl.java):
// 小车装饰者
public class CarDecoratorImpl extends AttachedPropertiesDecorator{
private String car = "有车";
public CarDecoratorImpl(Man man) {
super(man);
}
public void addCar() {
System.out.print(car + " ");
}
@Override
public void getManDesc() {
super.getManDesc();
addCar();
}
}
// 房子装饰者
public class HouseDecoratorImpl extends AttachedPropertiesDecorator{
private String house = "有房";
public HouseDecoratorImpl(Man man) {
super(man);
}
public void addHouse() {
System.out.print(house + " ");
}
@Override
public void getManDesc() {
super.getManDesc();
addHouse();
}
}
// 存款装饰者
public class DepositDecoratorImpl extends AttachedPropertiesDecorator{
private String deposit = "有存款";
public DepositDecoratorImpl(Man man) {
super(man);
}
public void addDeposit() {
System.out.print(deposit + " ");
}
@Override
public void getManDesc() {
super.getManDesc();
addDeposit();
}
}
// 品质装饰者
public class QualityDecoratorImpl extends AttachedPropertiesDecorator{
private String quality = "有好品质";
public QualityDecoratorImpl(Man man) {
super(man);
}
public void addQuality() {
System.out.print(quality + " ");
}
@Override
public void getManDesc() {
super.getManDesc();
}
}
有车、有房、有存款、有品质具体修饰者。
装饰者模式测试类(DecoratorTest.java):
public class DecoratorTest {
public static void main(String[] args) {
Man man = new NormalMan("张三");
Man man1 = new CarDecoratorImpl(man);
Man man2 = new HouseDecoratorImpl(man1);
Man man3 = new DepositDecoratorImpl(man2);
System.out.println("层层装饰:");
man3.getManDesc();
System.out.println();
System.out.println("重复装饰(有两个'有存款'):");
Man man4 = new DepositDecoratorImpl(man3);
man4.getManDesc();
System.out.println();
System.out.println("任意修饰:");
Man man5 = new QualityDecoratorImpl(man1);
man5.getManDesc();
System.out.println();
System.out.println("直接得到修饰结果:");
Man man6 = new HouseDecoratorImpl(new DepositDecoratorImpl(new NormalMan("李四")));
man6.getManDesc();
System.out.println();
}
}
运行结果:
四、优缺点
优点:
1、装饰者模式和继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活型。
2、通过使用不同的具体装饰者类及它们不同的组合顺序,可以得到不同装饰后具有不同行为或者状态的对象。例如上面的CarDecoratorImpl可以多次修饰一个男人,证明他有很多车。
3、符合开闭原则。
缺点:
1、增加了抽象装饰者类和具体装饰者类,一定程度增加了系统的复杂度,加大了系统的学习和理解成本。
2、灵活性也意味着更容易出错,对于多次被多次修饰的对象,调试时寻找错误可能需要找到多个地方。