装饰者模式

[size=medium]有时候为了传承某个类的一些功能,我们可以采用继承该类来获取功能,并可以通过覆写某些方法来进行功能加强。然而若想对一批类的功能进行加强,如果仍采用继承,不仅在代码上重复,并且不利于扩展。如下所示:[/size]

public interface Component {

public void fun();
}

public class ConcreteAComponent implements Component{

@Override
public void fun() {
System.out.println("ConcreteAComponent");
}

}

public class ConcreteBComponent implements Component{

@Override
public void fun() {
System.out.println("ConcreteBComponent");
}

}


[img]http://dl2.iteye.com/upload/attachment/0103/3470/8e98cf6f-d460-309b-bcd6-69230c04b950.png[/img]
[size=medium]接口Component有一个fun()方法,ConcreteAComponent、ConcreteBComponent都实现了该接口,完成了fun方法。现在的需求是,想对ConcreteAComponent、ConcreteBComponent所实现的fun方法进行加强,如想计算出fun方法所花费时间、想在fun方法执行前后输出一些信息等。

如果采用继承的话,加强ConcreteAComponent,则需要写一个类继承ConcreteAComponent,加强ConcreteBComponent,则需要写一个类继承ConcreteBComponent,就会造成每当要加强一个类时就必须要新建一个类继承它,在代码上造成严重的重复。
除了继承能够进行功能复用外,还有如下的复用方式:[/size]

public class ConcreteTimeDecorator implements Component{

private Component component;

public ConcreteTimeDecorator(Component component) {
super();
this.component = component;
}

@Override
public void fun() {
long start=System.currentTimeMillis();
System.out.println("start at "+start);
component.fun();
long end=System.currentTimeMillis();
System.out.println("end at "+end+",cost "+(end-start));
}

}

[size=medium]ConcreteTimeDecorator 是一个时间计算装饰器,ConcreteTimeDecorator 实现了Component接口主要是为了替代要装饰的Component 对象。它内部保留了一个Component 的引用,对于那些ConcreteTimeDecorator 并不关心的方法,有具体的Component 对象来实现,而对于想要增强的方法加上自己的逻辑,由于ConcreteTimeDecorator 针对的是接口Component ,不依赖于任何一个具体的Component ,所以每当要增强一个具体的Component时,不用再添加新的类,和继承就不一样了,这样更加容易扩展。

再如下一个装饰着:[/size]

public class ConcretePrintDecorator implements Component{

private Component component;

public ConcretePrintDecorator(Component component) {
super();
this.component = component;
}

@Override
public void fun() {
System.out.println("before real component run");
component.fun();
System.out.println("after real component run");
}

}

[size=medium]也是同样的道理。
我们使用装饰者模式:[/size]

ConcreteAComponent concreteAComponent=new ConcreteAComponent();

ConcreteTimeDecorator concreteTimeDecorator=new ConcreteTimeDecorator(concreteAComponent);
concreteTimeDecorator.fun();

System.out.println("--------------------------------------------");
ConcretePrintDecorator concretePrintDecorator=new ConcretePrintDecorator(concreteAComponent);
concretePrintDecorator.fun();

[size=medium]运行效果如下:[/size]

start at 1416349131419
ConcreteAComponent
end at 1416349131419,cost 0
--------------------------------------------
before real component run
ConcreteAComponent
after real component run

[size=medium]可见ConcreteTimeDecorator 、ConcretePrintDecorator 对ConcreteAComponent 进行装饰后,加强了对应的功能,同样他们可以对ConcreteBComponent进行装饰加强ConcreteBComponent的功能。整个类图就如下:

[img]http://dl2.iteye.com/upload/attachment/0103/3472/aee52be8-69c5-3c61-b54a-d3b0046b7f40.png[/img]
这里稍加改动了一些,把ConcreteTimeDecorator和ConcretePrintDecorator的一些共性部分拿出来,作为基类。

这就是装饰者模式,jdk中装饰者模式也很常见,如常用的BufferedInputStream,它就是对InputStream加入了缓冲功能来提高性能,如下所示:[/size]

[img]http://dl2.iteye.com/upload/attachment/0103/3474/0c9dfb72-a950-3884-8ddc-75241dc9b909.png[/img]
[size=medium]其中FilterInputStream就是一个装饰者的基类,它把所有装饰者共性的部分拿出来,即持有一个InputStream引用,如下:[/size]

public
class FilterInputStream extends InputStream {

protected volatile InputStream in;

protected FilterInputStream(InputStream in) {
this.in = in;
}
//略
}

[size=medium]这种形式和刚才上面的形式基本一样,然后BufferedInputStream再继承FilterInputStream 。

若想转载请注明出处: [url]http://lgbolgger.iteye.com/blog/2154368[/url]
作者:iteye的乒乓狂魔
[/size]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值