@pastqing
2015-11-12T17:00:53.000000Z
字数 2694
阅读 2924
java
设计模式
wiki是这样定义装饰器模式的:在面向对象编程的领域,一种动态的往一个类中添加新的行为的设计模式。就功能而言,装饰器模式相比生成子类更加灵活,这样可以给某个对象而不是整个类添加一些功能。
通过装饰器模式可以在运行时扩充一个类的功能。增加一个修饰类包裹原来的类,包裹的方式一般是通过在将原来的对象作为修饰类的构造函数的参数。装饰类实现新的功能,但是,在不需要用到新功能的地方,它可以直接调用原来的类中的方法。修饰类必须和原来的类有相同的接口。
下面是装饰器的基本类图:
装饰器模式的基本角色:
public interface Component {
public void method();
}
public class ConcreteComponent implements Component{
public void method() {
System.out.println("The basic method");
}
}
public abstract class Decorator implements Component{
protected Component component;
public Decorator(Component component) {
this.component = component;
}
public void method() {
component.method();
}
}
public class ConcreteDecoratorA extends Decorator{
public ConcreteDecoratorA(Component component) {
super(component);
}
public void method() {
//先调用原始方法, 在执行扩展方法
super.method();
System.out.println("DecoratorA add sth");
}
//扩展的其他方法...
public void methodA() {
System.out.println("method A");
}
...
}
一个装饰类同样可以被另一个装饰器类所装饰。利用组合而不是继承的形式来扩展某个类, 使其更加灵活。
我们构造这样一个情景:某个应用的数据访问层上,实现持久化的技术有很多种mybaits,jdbc等等。如此我们设计一个接口:
public interface GenerateInterface<T> {
//创建一条记录
public void save(T data);
//更新一条记录
public void update(T data);
}
不同的ORM技术,我们分别设计两个类:
public class MybatisORM<T> implements GenerateInterface<T> {
@Override
public void save(T data) {
//mybatis save
System.out.println("mybaits save");
}
@Override
public void update(T data) {
//mybatis update
System.out.println("mybatis update");
}
}
public class JdbcORM<T> implements GenerateInterface<T> {
@Override
public void save(T data) {
//insert data into table with jdbc
System.out.println("jdbc save");
}
@Override
public void update(T data) {
//update data to table with jdbc
System.out.println("jdbc update");
}
}
现在新增一个需求,是我们在持久化数据的时候, save or update时同时更新日志,这时候为了不更改原有代码, 也不使用继承,我们采用装饰器模式,定义一个装饰者。
public class LogDecoratorORM <T> implements GenerateInterface<T>{
private GenerateInterface<T> generator;
public LogDecoratorORM(GenerateInterface<T> generator) {
this.generator = generator;
}
private void logSave(T data) {
//to insert log table
System.out.println("log save");
}
private void logUpdate(T data) {
//to update log table
System.out.println("log update");
}
@Override
public void save(T data) {
logSave(data);
generator.save(data);
}
@Override
public void update(T data) {
logUpdate(data);
generator.save(data);
}
}
如此就可以实现需求的变动。
JDK中IO体系的设计就是基于装饰器模式的。我们先看个简单的IO体系类图:
InputSteam相当于上面模型的Component
FileInputStream就是InputSteam的实现类了。
BufferedInputSteam, DataInputSteam等就是具体的装饰类了。
装饰器模式的优点:
装饰器模式的缺点: