装饰者模式

简介:
有时候为了传承某个类的一些功能,我们可以采用继承该类来获取功能,并可以通过覆写某些方法来进行功能加强。然而若想对一批类的功能进行加强,如果仍采用继承,不仅在代码上重复,并且不利于扩展。如下所示:  
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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" );
     }
 
}


 
接口Component有一个fun()方法,ConcreteAComponent、ConcreteBComponent都实现了该接口,完成了fun方法。现在的需求是,想对ConcreteAComponent、ConcreteBComponent所实现的fun方法进行加强,如想计算出fun方法所花费时间、想在fun方法执行前后输出一些信息等。 

如果采用继承的话,加强ConcreteAComponent,则需要写一个类继承ConcreteAComponent,加强ConcreteBComponent,则需要写一个类继承ConcreteBComponent,就会造成每当要加强一个类时就必须要新建一个类继承它,在代码上造成严重的重复。 
除了继承能够进行功能复用外,还有如下的复用方式:
 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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));
     }
 
}

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

再如下一个装饰着:
 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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" );
     }
 
}

也是同样的道理。 
我们使用装饰者模式:
 
?
1
2
3
4
5
6
7
8
ConcreteAComponent concreteAComponent= new ConcreteAComponent();
         
         ConcreteTimeDecorator concreteTimeDecorator= new ConcreteTimeDecorator(concreteAComponent);
         concreteTimeDecorator.fun();
         
         System.out.println( "--------------------------------------------" );
         ConcretePrintDecorator concretePrintDecorator= new ConcretePrintDecorator(concreteAComponent);
         concretePrintDecorator.fun();

运行效果如下:  
?
1
2
3
4
5
6
7
start at 1416349131419
ConcreteAComponent
end at 1416349131419 ,cost 0
--------------------------------------------
before real component run
ConcreteAComponent
after real component run

可见ConcreteTimeDecorator 、ConcretePrintDecorator 对ConcreteAComponent 进行装饰后,加强了对应的功能,同样他们可以对ConcreteBComponent进行装饰加强ConcreteBComponent的功能。整个类图就如下: 
  
 
这里稍加改动了一些,把ConcreteTimeDecorator和ConcretePrintDecorator的一些共性部分拿出来,作为基类。 

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

 
其中FilterInputStream就是一个装饰者的基类,它把所有装饰者共性的部分拿出来,即持有一个InputStream引用,如下:  
?
1
2
3
4
5
6
7
8
9
10
public
class FilterInputStream extends InputStream {
    
     protected volatile InputStream in;
 
     protected FilterInputStream(InputStream in) {
         this .in = in;
     }
    //略
}

这种形式和刚才上面的形式基本一样,然后BufferedInputStream再继承FilterInputStream 。 
相关文章
|
6月前
结构型 装饰器模式
结构型 装饰器模式
32 0
|
6月前
|
设计模式 Java
Java设计模式【十】:装饰者模式
Java设计模式【十】:装饰者模式
50 0
|
29天前
|
设计模式 缓存 C#
C# 一分钟浅谈:装饰者模式与代理模式
【10月更文挑战第12天】本文介绍了面向对象编程中的两种常见设计模式:装饰者模式和代理模式。装饰者模式允许在运行时动态地给对象添加功能,而代理模式则通过代理对象控制对另一个对象的访问。文章详细讲解了这两种模式的概念、常见问题、如何避免问题以及代码示例,帮助读者更好地理解和应用这些设计模式。
36 13
|
6月前
|
设计模式
装饰器模式
装饰器模式
33 0
|
6月前
|
设计模式 C++
【C++】—— 装饰器模式
【C++】—— 装饰器模式
装饰者模式
装饰者模式
72 0
|
设计模式
2023-6-26-第八式装饰器模式
2023-6-26-第八式装饰器模式
74 0
|
前端开发 BI
关于装饰器模式我所知道的
关于装饰器模式我所知道的
77 0
|
设计模式
我认为的装饰器模式
我认为的装饰器模式
97 0
|
Java
结构型模式-装饰者模式
结构型模式-装饰者模式
88 0