装饰者模式也称为包装模式(Wrapper Pattern),属于结构型设计模式。
该模式对客户端透明的方式来动态的扩展对象,(对扩展开放,对修改关闭)
同时该模式也是继承关系的一种替代方法之一。
总之就是动态的给对象添加一些额外的职责,类似钢铁侠可以组装不同武器。
1.装饰者和被装饰者有相同的超类(Component)。
2.你可以用一个或多个具体装饰(ConcreteDecorator)包装一个对象。
3.装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。(类似代理模式)
4.对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。
基于装饰者模式,我们直接进行实战。
譬如目前接到一个需求,需要对Bitmap做处理,有各种各样的功能 : 美瞳,瘦脸,滤镜,磨皮,老电影等效果。
按照以往习惯,可能会创建 磨皮类 继承 瘦脸类 继承 美瞳类。 这么继承下去不仅会类爆炸,而且一旦中间功能需要删改,往往就要重写整个类。
抽象组件(IComponentBitmap)
public interface IComponentBitmap {
/**
* 定义方法规范
* 同样的也可以增加更多的抽象方法
*/
public void bmpOperation(Bitmap bmp);
}
被装饰者(ConcreteBitmap)
/**
* 要接收附加装饰的基类
* 具有通用属性
*/
public class ConcreteBitmap implements IComponentBitmap{
@Override
public void bmpOperation(Bitmap bmp) {
bmp.description=new StringBuffer("原始bmp");
}
}
装饰者组件(BitmapDecorator)
/**
* 装饰角色 持有一个Component对象的实例
* 对具体装饰者可以做统一基础处理
*/
public class BitmapDecorator implements IComponentBitmap {
protected IComponentBitmap mComponent;
public BitmapDecorator(IComponentBitmap component) {
mComponent = component;
}
@Override
public void bmpOperation(Bitmap bmp) {
mComponent.bmpOperation(bmp);//可以做基础操作
}
}
以下是具体装饰类。
/**
* 具体装饰类
* 滤镜装饰
*/
public class FilterBitmapDecorator extends BitmapDecorator{
public FilterBitmapDecorator(IComponentBitmap component) {
super(component);
}
@Override
public void bmpOperation(Bitmap bmp) {
bmp.description.append("+滤镜效果");
}
}
/**
* 具体装饰类
* 老电影效果
*/
public class MovieBitmapDecorator extends BitmapDecorator{
public MovieBitmapDecorator(IComponentBitmap component) {
super(component);
}
@Override
public void bmpOperation(Bitmap bmp) {
bmp.description.append("+老电影效果");
}
}
客户端类 :
Bitmap bmp=new Bitmap();
IComponentBitmap concreteBmp=new ConcreteBitmap();//创建被装饰者
concreteBmp.bmpOperation(bmp);//无任何装饰
System.out.println(bmp.description);
/*****************原始bmp*****************/
new FilterBitmapDecorator(concreteBmp).bmpOperation(bmp);;
System.out.println(bmp.description);
/*****************原始bmp+滤镜效果*****************/
new MovieBitmapDecorator(concreteBmp).bmpOperation(bmp);
System.out.println(bmp.description);
/*****************原始bmp+滤镜效果+老电影效果*****************/
对于bmp的装饰需求,我们可以写出各种具体装饰类,通过不同的拼接实现不同的效果。增强对象的拓展功能。
read()
,子类都需要对该方法进行处理read()
基本方法
装饰者模式让我们可以有不同的被装饰者,例如FileInputStream
,并且如果想使用缓冲功能那么只需写一下代码 :
new BufferedInputStream(new FileInputStream(new File("path")));
也可以对上面代码再进行加工,简单的加密处理 :
new Base64InputStream(new BufferedInputStream(new FileInputStream(new File(""))),0)
哪怕你突然改需求了,读取的对象不是文件,而是文本或字符,那么可以轻松的将代码改为 :
new Base64InputStream(new BufferedInputStream(new StringBufferInputStream("str")),0)
装饰者模式能够很好的增强对象的拓展功能,如果抽象组件定义的类型是人(抽象方法是攻击力)
那么被装饰者可以是“法师”,“战士”,“射手”,“肉坦”,装饰者模式可以让我们无需关注这些被装饰者(ConcreteComponent)
我们可以实现不同的装饰功能(ConcreteDecorator),例如匕首(+5),长剑(+10),法杖(+1)
OO原则:动态地将责任附加到对象上。想要扩展功能, 装饰者提供有别于继承的另一种选择。
1、继承属于扩展形式之一,但不见得是达到弹性设计的最佳方案。
2、在我们的设计中,应该允许行为可以被扩展,而不须修改现有的代码。
3、组合和委托可用于在运行时动态地加上新的行为。
4、除了继承,装饰者模式也可以让我们扩展行为。
5、装饰者模式意味着一群装饰者类, 这些类用来包装具体组件。
6、装饰者类反映出被装饰的组件类型(实际上,他们具有相同的类型,都经过接口或继承实现)。
7、装饰者可以在被装饰者的行为前面与/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的。
8、你可以有无数个装饰者包装一个组件。
9、装饰者一般对组建的客户是透明的,除非客户程序依赖于组件的具体类型。