目录
什么是设计模式
装饰模式又名包装模式。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
有透明和半透明两种,大部分都是半透明的,半透明的装饰模式是介于装饰模式和适配器模式之间的。
装饰模式的核心:功能扩展。
透明和半透明的区别:
透明的装饰模式,要求具体构件角色、装饰角色的接口与抽象构件角色的接口完全一致。意思是奶茶接口、珍珠奶茶和蜂蜜奶茶、调料的这些接口一样。下面代码中会有体现。相反,如果装饰角色的接口与抽象构件角色接口不一致,那就是半透明的了。
优缺点
优点
- 动态扩展类功能,比类继承灵活,且对客户端透明;
- 继承关系的一种替代方案。相比与类继承的父子关系,装饰模式更像是一种组合关系(is-a);
- 可以对同一个被装饰对象进行多次装饰,创建出不同行为的复合功能;
缺点
- 多层装饰比较复杂(灵活的同时会带来复杂性的增加);
- 装饰嵌套过多,会产生过多小对象(每个装饰层都创建一个相应的对象);
- 装饰嵌套过多,易于出错,且调试排查比较麻烦(需要一层一层对装饰器进行排查,以确定是哪一个装饰层出错);
装饰模式UML
抽象组件(Component):
可以是一个接口或者抽象类,其充当被装饰类的原始对象,规定了被装饰对象的行为;
具体组件(ConcreteComponent):
实现/继承 Component 的一个具体对象,也即被装饰对象;
抽象装饰器(Decorator):
通用的装饰ConcreteComponent的装饰器,其内部必然有一个属性指向Component抽象组件;其实现一般是一个抽象类,主要是为了让其子类按照其构造形式传入一个Component抽象组件,这是强制的通用行为(当然,如果系统中装饰逻辑单一,并不需要实现许多装饰器,那么我们可以直接省略该类,而直接实现一个具体装饰器(ConcreteDecorator) 即可);
具体装饰器(ConcreteDecorator):
Decorator 的具体实现类,理论上,每个 ConcreteDecorator 都扩展了 Component 对象的一种功能;
总结:
装饰模式 角色分配符合设计模式里氏替换原则,依赖倒置原则,从而使得其具备很强的扩展性,最终满足开闭原则。
代码实现
Component抽象类
Component是一个接口或是抽象类,就是定义我们最核心的对象,也就是最原始的对象。
/** * 抽象类 */ public abstract class Conpontent { public abstract void operation(); }
ConretetComponent类
具体构件,通过继承实现Component抽象类中的抽象方法。是最核心、最原始、最基本的接口或抽象类的实现,我们要装饰的就是它。
/** * 实现Component的抽象方法 */ public class ConcreteComponent extends Conpontent { @Override public void operation() { Log.d(TAG, " ConcreteComponent operation : "); } }
Decorator装饰类
一般是一个抽象类,在其属性里必然有一个private变量指向Component抽象构件。
/** * 装饰者类 */ public abstract class Decorator extends Conpontent { private Conpontent conpontent = null; public Decorator(Conpontent conpontent) { this.conpontent = conpontent; } @Override public void operation() { if (null != conpontent) { conpontent.operation(); } } }
ConcreteDecorator类
可以写多个具体实现类,把最核心的、最原始的、最基本的东西装饰成其它东西。
如下写两个类ConcreateDecoratorA和ConcreateDecoratorB。
/** * 装饰者具体实现类A */ public class ConcreateDecoratorA extends Decorator { public ConcreateDecoratorA(Conpontent conpontent) { super(conpontent); } private void method() { Log.d(TAG, "ConcreateDecoratorA method : "); return; } @Override public void operation() { super.operation(); this.method(); } }
/** * 装饰者具体实现类B */ public class ConcreateDecoratorB extends Decorator { public ConcreateDecoratorB(Conpontent conpontent) { super(conpontent); } private void method() { Log.d(TAG, "ConcreateDecoratorB method : "); return; } @Override public void operation() { super.operation(); this.method(); } }
Conpontent conpontent = new ConcreteComponent(); conpontent = new ConcreateDecoratorA(conpontent); conpontent= new ConcreateDecoratorB(conpontent); conpontent.operation();