第二十一章、装饰模式
装饰模式也称为包装模式。是结构型设计模式之中的一个。装饰模式是一种用于替代继承技术的一种方案。
1.定义
动态的给一个对象加入一些额外的职责。就添加功能来说。装饰模式相比生成子类更为灵活。
2.使用场景
(1)须要透明且动态地扩展类的功能时。且在不影响其它对象的情况下。
(2)当不能採用继承对系统进行扩展时能够使用装饰模式。比方final类。
3.UML类图
(1)Component
:抽象组件。
能够是一个接口或抽象类。其充当的就是被装饰的原始对象。
(2)ConcreteComponent
:组件详细实现类,该类是Component类的基本实现,也是我们装饰的详细对象。
(3)Decorator
:抽象装饰者。其职责就是装饰我们的组件对象,通过其子类扩展该方法以达到装饰的目的。其内部一定要有一个指向组件对象的引用。在大多数情况下。该类为抽象类。须要依据不同的装饰逻辑实现不同的详细子类。
(4)ConcreteDecoratorA
、ConcreteDecoratorB
:装饰着详细实现类。负责向构件加入新的职责。
4.简单实现
以一个男孩穿衣装扮为例。实现给男孩在家与出门的穿衣装扮。
抽象组件类(Component):
public abstract class Person {
/**
* Person下有一个穿着的抽象方法
*/
public abstract void dressed();
}
详细实现类(ConcreteComponent):表示要装扮的Boy
public class Boy extends Person{
@Override
public void dressed() {
System.out.println("Boy穿了内衣内裤");
}
}
抽象装饰类(Decorator):PersonCloth 表示人所穿着的衣服
public class PersonCloth extends Person{
protected Person mPerson; //保持一个Person类的引用
public PersonCloth(Person mPerson) {
super();
this.mPerson = mPerson;
}
@Override
public void dressed() {
mPerson.dressed();
}
}
出门穿的衣服:
public class OutsideCloth extends PersonCloth{
public OutsideCloth(Person mPerson) {
super(mPerson);
}
/**
* 穿短袖
*/
private void dressShirt(){
System.out.println("穿件短袖");
}
/**
* 穿牛仔裤
*/
private void dressJean(){
System.out.println("穿牛仔裤");
}
/**
* 穿鞋子
*/
private void dressShoes(){
System.out.println("穿鞋子 ");
}
@Override
public void dressed() {
super.dressed();
dressShirt();
dressJean();
dressShoes();
}
}
在家穿的衣服:
public class HomeCloth extends PersonCloth{
public HomeCloth(Person mPerson) {
super(mPerson);
}
/**
* 穿短裤
*/
private void dressShorts(){
System.out.println("穿短裤");//在家里随便点
}
@Override
public void dressed() {
super.dressed();
dressShorts();
}
}
装扮:
public class Client {
public static void main(String[] args) {
//首先有一个男孩
Person person = new Boy();
//在家
PersonCloth personCloth = new HomeCloth(person);
personCloth.dressed();
System.out.println("--------------");
//出门
PersonCloth personCloth1 = new OutsideCloth(person);
personCloth1.dressed();
}
}
结果
Boy穿了内衣内裤
穿短裤
--------------
Boy穿了内衣内裤
穿件短袖
穿牛仔裤
穿鞋子
5.Android源代码中的实现
1.Context
Context
类在Android中被称为“上帝对象”,它的本质就是一个抽象类,在装饰模式中相当于抽象组件。而在内部定义了大量的抽象方法。比方我们经经常使用到的startActivity
方法。
而真正实现是在ContextImpl
中完毕,那么ContextImpl
就是详细实现类。由于ContextWrapper
继承于Context
,所以ContextWrapper
就是装饰者。
详细大家能够自行查看源代码。
6.差别
1.与代理模式的差别
(1)装饰模式是以对client透明的方式扩展对象的功能,是继承方案的一个替代。而代理模式则是给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用。
(2)装饰模式应该为所装饰的对象增强功能;代理模式是对代理对象施加控制,不正确对象本身功能进行增强。
2.与适配器模式的差别
适配器模式是用新接口来调用原接口,原接口对新系统是不可见的;装饰模式增强了其它对象的功能而同一时候又不改变它的接口。
7.总结
在实际开发中我们应该写过例如以下代码:事实上这些新增方法的调用就相似装饰模式中的装饰者的职责。仅仅只是这里我们没有保持对组件类的引用。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化数据
initData();
//初始化控件
initViews();
//初始化事件
initEvent();
}
1.长处
(1)对于扩展一个对象的功能,装饰模式比继承更加灵活性,不会导致类的个数急剧添加。
(2)能够通过一种动态的方式在执行时选择不同的详细装饰类,从而实现不同的行为。
(3)能够对一个对象进行多次装饰。通过使用不同的详细装饰类以及这些装饰类的排列组合,能够创造出非常多不同行为的组合。得到功能更为强大的对象。
(4)详细构件类与详细装饰类能够独立变化。用户能够依据须要添加新的详细构件类和详细装饰类,原有类库代码无须改变。符合“开闭原则”。
2.缺点
(1)使用装饰模式进行系统设计时将产生非常多小对象,这些对象的差别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,大量小对象的产生势必会占用很多其它的系统资源,在一定程序上影响程序的性能。
(2)对于多次装饰的对象,调试时寻找错误可能须要逐级排查,较为繁琐。