一句话:需要包装,但不改变本质(同宗同源)。
在不改变原有对象的基础之上,将功能附加到对象上。提供了比继承更有弹性的替代方案(扩展原有对象功能)
特点:
1、注重覆盖、扩展。
2、装饰器和被装饰器都实现同一个接口,主要目的是为了扩展之后依旧保留 OOP 关系(同宗同源)。
3、满足 is-a 的关系。
扩展一个类的功能或者给一个类添加附加职责
给一个对象动态的添加功能,或动态撤销功能。
IO 流包装
FilterInputStream filterInputStreasm = new BufferedInputStream(new FileInputStream(new File("/user/a")));
前台表单页面填写中文,通过servlet请求传递到后台,如果不经过任何处理,前台默认通过UTF-8编码,后台默认iso-8859-1解码,编码方式的差异难免造成乱码问题,可以用装饰者模式处理该问题。
数据源包装
在我们的项目中遇到这样一个问题:我们的项目需要连接多个数据库,而且不同的客户在每 次访问中根据需要会去访问不同的数据库。我们以往在 Spring 和 Hibernate 框架中总是配置一个数据 源,因而 SessionFactory 的 DataSource 属性总是指向这个数据源并且恒定不变,所有 DAO 在使用 SessionFactory 的时候都是通过这个数据源访问数据库。但是现在,由于项目的需要,我们的 DAO 在 访 问 SessionFactory 的 时 候 都 不 得 不 在 多 个 数 据 源 中 不 断 切 换 , 问 题 就 出 现 了 : 如 何 让 SessionFactory 在执行数据持久化的时候,根据客户的需求能够动态切换不同的数据源?我们能不能 在 Spring 的框架下通过少量修改得到解决?是否有什么设计模式可以利用呢? 首先想到在 Spring 的 ApplicationContext 中配置所有的 DataSource。这些 DataSource 可能是各 种不同类型的,比如不同的数据库:Oracle、SQL Server、MySQL 等,也可能是不同的数据源:比如 Apache 提 供 的 org.apache.commons.dbcp.BasicDataSource 、 Spring 提 供 的 org.springframework.jndi.JndiObjectFactoryBean 等。然后 SessionFactory 根据客户的每次 请求,将 DataSource 属性设置成不同的数据源,以到达切换数据源的目的。 Spring 中用到的包装器模式在类名上有两种表现:一种是类名中含有 Wrapper,另一种是类名中含有 Decorator。基本上都是动态地给一个对象添加一些额外的职责。
简历包装
一般当我们需要在具体的类中都需涛执行一些特定的操作时。我们一般就会使用抽象类,并定义抽象方法。
要点:
(1)抽象组件(Component):给出一个抽象接口,以规范准备接受附加责任的对象。
(2)被装饰者(ConcreteComponent):Component的具体实现,也就是我们要装饰的具体对象。
(3)装饰者组件(Decorator):持有组件对象的实例引用,该类的职责就是为了装饰具体组件对象,定义的基类。
(4)具体装饰(ConcreteDecorator):负责给构件对象装饰附加的功能。
总结起来就是,如果想对一个行为在不改变原来基础上加新功能和扩展,首先先把该行为抽象出来。然后实现抽象行为,原来的行为具体实现该抽象行为,创建一个抽象行为也实现同一个抽象行为,如果要装饰的时候,再在具体实现该装饰抽象类。
使用案例:
绞尽脑筋想不到很好的案例,网上很多其他的案例可以参考,但大部分都是卖东西
下面就结合自身写个案例吧
作为一名技术宅程序员,166的身高普通的样貌,不善言辞的嘴巴,至今一直单身,家里人为止着急上火,本人也很无奈,被嫌弃太多,习惯成自然,以后要自信。
下面用装饰模式给自己装饰一番,看魅力值有没有提高半分。
开撸:
//原来抽象 的我
public interface AbstractMyself {
//身高
public long getHeight();
//样貌
public String getAppearance();
//言谈
public String getSpeech();
}
//原來的我
public class Myself implements AbstractMyself {
@Override
public long getHeight() {
return 166;
}
@Override
public String getAppearance() {
return "普通";
}
@Override
public String getSpeech() {
return "不善言辞";
}
}
//抽象装饰后的我
public abstract class AbstractDecorator implements AbstractMyself {
private AbstractMyself abstractMyself;
public AbstractDecorator(AbstractMyself abstractMyself) {
this.abstractMyself = abstractMyself;
}
@Override
public long getHeight() {
return this.abstractMyself.getHeight();
}
@Override
public String getAppearance() {
return this.abstractMyself.getAppearance();
}
@Override
public String getSpeech() {
return this.abstractMyself.getSpeech();
}
}
//具体装饰后的我
/**
* 提升后的我
*/
public class PromoteMyself extends AbstractDecorator {
public PromoteMyself(AbstractMyself myself) {
super(myself);
}
//穿增高鞋
@Override
public long getHeight() {
return super.getHeight() + 8;
}
@Override
public String getAppearance() {
return "保养皮肤";
}
@Override
public String getSpeech() {
return "多读书,多当众讲话";
}
}
//测试
public class Test {
public static void main(String[] args) {
//原来的我
AbstractMyself myself = new Myself();
System.out.println(myself.getAppearance() + myself.getSpeech() + myself.getHeight());
//裝飾后的我
PromoteMyself promoteMyself = new PromoteMyself(myself);
System.out.println(promoteMyself.getAppearance() + promoteMyself.getSpeech() + promoteMyself.getHeight());
}
}