装饰模式 迷南。 2022-02-16 19:11 207阅读 0赞 # 概述 # 23种设计模式之一,英文叫DecoratorPattern,中文也叫装饰模式、修饰模式。装饰模式是在不改变类文件和不使用继承的情况下,运行期动态扩展一个对象的功能。原理是:增加一个修饰类包裹原来的类,包裹的方式一般是通过在将原来的对象作为修饰类的构造函数的参数。装饰类实现新的功能,但是,在不需要用到新功能的地方,它可以直接调用原来的类中的方法。修饰类必须和原来的类有相同的接口(没有接口可以直接继承自原来的类)。修饰模式是类继承的另外一种选择。类继承在编译时候增加行为,而装饰模式是在运行时增加行为。 # UML # ![1353395508_5006.png][] # 实现 # Component.java,接口。 <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p><strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">interface</span></strong> Component { </p> <p> <strong><span style="color:rgb(127,0,85)">void</span></strong> operation();</p> <p>}</p> </td> </tr> </tbody> </table> ConcreteComponent.java,原有类实现(需要扩展)。 <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p><strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">class</span></strong> ConcreteComponent <strong><span style="color:rgb(127,0,85)">implements</span></strong> Component { </p> <p> <strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">void</span></strong> operation() { </p> <p> System.<em><span style="color:rgb(0,0,192)">out</span></em>.println(<span style="color:rgb(42,0,255)">"</span><span style="color:rgb(42,0,255)">具体对象的操作</span><span style="color:rgb(42,0,255)">"</span>);</p> <p> }</p> <p>}</p> </td> </tr> </tbody> </table> Decorator.java,抽象修饰类。 <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p><strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">abstract</span> <span style="color:rgb(127,0,85)">class</span></strong> Decorator <strong><span style="color:rgb(127,0,85)">implements</span></strong> Component { </p> <p> <strong><span style="color:rgb(127,0,85)">protected</span></strong> Component<span style="color:rgb(0,0,192)">component</span>;</p> <p> <strong><span style="color:rgb(127,0,85)">public</span></strong> Decorator(Component component) { </p> <p> <strong><span style="color:rgb(127,0,85)">this</span></strong>.<span style="color:rgb(0,0,192)">component</span> = component;</p> <p> }</p> <p> <strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">void</span></strong> operation() { </p> <p> <strong><span style="color:rgb(127,0,85)">if</span></strong>(<span style="color:rgb(0,0,192)">component</span> !=<strong><span style="color:rgb(127,0,85)">null</span></strong>)</p> <p> <span style="color:rgb(0,0,192)">component</span>.operation();</p> <p> }</p> <p>}</p> </td> </tr> </tbody> </table> ConcreteDecoratorA.java,实际修饰类A。 <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p><strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">class</span></strong> ConcreteDecoratorA <strong><span style="color:rgb(127,0,85)">extends</span></strong> Decorator { </p> <p> <strong><span style="color:rgb(127,0,85)">public</span></strong> ConcreteDecoratorA(Component component) { </p> <p> <strong><span style="color:rgb(127,0,85)">super</span></strong>(component);</p> <p> }</p> <p> <span style="color:rgb(100,100,100)">@Override</span></p> <p> <strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">void</span></strong> operation() { </p> <p> <strong><span style="color:rgb(127,0,85)">super</span></strong>.operation();</p> <p> System.<em><span style="color:rgb(0,0,192)">out</span></em>.println(<span style="color:rgb(42,0,255)">"</span><span style="color:rgb(42,0,255)">对象</span><span style="color:rgb(42,0,255)">A</span><span style="color:rgb(42,0,255)">扩展的操作</span><span style="color:rgb(42,0,255)">"</span>);</p> <p> }</p> <p>}</p> </td> </tr> </tbody> </table> ConcreteDecoratorB.java,实际修饰类B。 <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p><strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">class</span></strong> ConcreteDecoratorB <strong><span style="color:rgb(127,0,85)">extends</span></strong> Decorator { </p> <p> <strong><span style="color:rgb(127,0,85)">public</span></strong> ConcreteDecoratorB(Component component) { </p> <p> <strong><span style="color:rgb(127,0,85)">super</span></strong>(component);</p> <p> }</p> <p> <span style="color:rgb(100,100,100)">@Override</span></p> <p> <strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">void</span></strong> operation() { </p> <p> <strong><span style="color:rgb(127,0,85)">super</span></strong>.operation();</p> <p> System.<em><span style="color:rgb(0,0,192)">out</span></em>.println(<span style="color:rgb(42,0,255)">"</span><span style="color:rgb(42,0,255)">对象</span><span style="color:rgb(42,0,255)">B</span><span style="color:rgb(42,0,255)">扩展的操作</span><span style="color:rgb(42,0,255)">"</span>);</p> <p> }</p> <p>}</p> </td> </tr> </tbody> </table> DecoratorTest.java,客户端。 <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p><strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">class</span></strong> DecoratorTest { </p> <p> <strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">static</span> <span style="color:rgb(127,0,85)">void</span></strong> main(String[] args) { </p> <p> Component component =</p> <p> <strong><span style="color:rgb(127,0,85)">new</span></strong> ConcreteDecoratorB(</p> <p> <strong><span style="color:rgb(127,0,85)">new</span></strong> ConcreteDecoratorA(</p> <p> <strong><span style="color:rgb(127,0,85)">new</span></strong> ConcreteComponent()));</p> <p> component.operation();</p> <p> }</p> <p>}</p> </td> </tr> </tbody> </table> 输出结果: <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p>具体对象的操作</p> <p>对象A扩展的操作</p> <p>对象B扩展的操作</p> </td> </tr> </tbody> </table> 上面客户端的调用方式是不是和如下的代码有些类似,没错,Java中的I/O类库使用的就是装饰模式。 <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p>BufferedInputStream bis =</p> <p><strong><span style="color:rgb(127,0,85)">new</span></strong> BufferedInputStream(</p> <p><strong><span style="color:rgb(127,0,85)">new</span></strong> FileInputStream(<span style="color:rgb(42,0,255)">""</span>));</p> </td> </tr> </tbody> </table> 上面就是装饰模式的模型,如果有不明白,可以结合代码、UML、定义一起看一下。 # 实例 # ## 需求 ## 一个窗口系统中的窗口,允许这个窗口内容滚动,我们希望给它添加水平或垂直滚动条(维基百科)。 ## 实现 ## Window.java,窗口接口。 <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p><strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">interface</span></strong> Window { </p> <p> <strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">void</span></strong> draw();</p> <p> <strong><span style="color:rgb(127,0,85)">public</span></strong> String getDescription();</p> <p>}</p> </td> </tr> </tbody> </table> SimpleWindow.java,简单窗口,不带任何修饰。 <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p><strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">class</span></strong> SimpleWindow <strong><span style="color:rgb(127,0,85)">implements</span></strong> Window { </p> <p> <strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">void</span></strong> draw() { <span style="color:rgb(63,127,95)">// draw window</span> }</p> <p> <strong><span style="color:rgb(127,0,85)">public</span></strong> String getDescription() { </p> <p> <strong><span style="color:rgb(127,0,85)">return</span></strong> <span style="color:rgb(42,0,255)">"simple window"</span>;</p> <p> }</p> <p>}</p> </td> </tr> </tbody> </table> WindowDecorator.java,窗口装饰抽象类。 <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p><strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">abstract</span> <span style="color:rgb(127,0,85)">class</span></strong> WindowDecorator<strong><span style="color:rgb(127,0,85)">implements</span></strong> Window { </p> <p> <strong><span style="color:rgb(127,0,85)">protected</span></strong> Window<span style="color:rgb(0,0,192)">decoratedWindow</span>;<span style="color:rgb(63,127,95)">// the Window being decorated</span></p> <p> <strong><span style="color:rgb(127,0,85)">public</span></strong> WindowDecorator(Window decoratedWindow) { </p> <p> <strong><span style="color:rgb(127,0,85)">this</span></strong>.<span style="color:rgb(0,0,192)">decoratedWindow</span> = decoratedWindow;</p> <p> }</p> <p>}</p> </td> </tr> </tbody> </table> HorizontalScrollBarDecorator.java,横向滚动条装饰类。 <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p><strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">class</span></strong> HorizontalScrollBarDecorator <strong><span style="color:rgb(127,0,85)">extends</span></strong> WindowDecorator { </p> <p> <strong><span style="color:rgb(127,0,85)">public</span></strong> HorizontalScrollBarDecorator(Window decoratedWindow) { </p> <p> <strong><span style="color:rgb(127,0,85)">super</span></strong>(decoratedWindow);</p> <p> }</p> <p> <strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">void</span></strong> draw() { </p> <p> drawHorizontalScrollBar();</p> <p> <span style="color:rgb(0,0,192)">decoratedWindow</span>.draw();</p> <p> }</p> <p> <strong><span style="color:rgb(127,0,85)">private</span> <span style="color:rgb(127,0,85)">void</span></strong> drawHorizontalScrollBar() { </p> <p> <span style="color:rgb(63,127,95)">// draw the horizontal scrollbar</span></p> <p> }</p> <p> <strong><span style="color:rgb(127,0,85)">public</span></strong> String getDescription() { </p> <p> <strong><span style="color:rgb(127,0,85)">return</span></strong> <span style="color:rgb(0,0,192)">decoratedWindow</span>.getDescription() + <span style="color:rgb(42,0,255)">", including horizontal scrollbars"</span>;</p> <p> }</p> <p>}</p> </td> </tr> </tbody> </table> VerticalScrollBarDecorator.java,纵向滚动条装饰类。 <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p><strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">class</span></strong> VerticalScrollBarDecorator <strong><span style="color:rgb(127,0,85)">extends</span></strong> WindowDecorator { </p> <p> <strong><span style="color:rgb(127,0,85)">public</span></strong> VerticalScrollBarDecorator(Window decoratedWindow) { </p> <p> <strong><span style="color:rgb(127,0,85)">super</span></strong>(decoratedWindow);</p> <p> }</p> <p> <strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">void</span></strong> draw() { </p> <p> drawVerticalScrollBar();</p> <p> <span style="color:rgb(0,0,192)">decoratedWindow</span>.draw();</p> <p> }</p> <p> <strong><span style="color:rgb(127,0,85)">private</span> <span style="color:rgb(127,0,85)">void</span></strong> drawVerticalScrollBar() { </p> <p> <span style="color:rgb(63,127,95)">// draw the vertical scrollbar</span></p> <p> }</p> <p> <strong><span style="color:rgb(127,0,85)">public</span></strong> String getDescription() { </p> <p> <strong><span style="color:rgb(127,0,85)">return</span></strong> <span style="color:rgb(0,0,192)">decoratedWindow</span>.getDescription() + <span style="color:rgb(42,0,255)">", including vertical scrollbars"</span>;</p> <p> }</p> <p>}</p> </td> </tr> </tbody> </table> DecoratedWindowTest.java,客户端。 <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p><strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">class</span></strong> DecoratedWindowTest { </p> <p> <strong><span style="color:rgb(127,0,85)">public</span> <span style="color:rgb(127,0,85)">static</span> <span style="color:rgb(127,0,85)">void</span></strong> main(String[] args) { </p> <p> <span style="color:rgb(63,127,95)">// create a decorated Window with horizontal and vertical scrollbars</span></p> <p> Window decoratedWindow =</p> <p> <strong><span style="color:rgb(127,0,85)">new</span></strong> HorizontalScrollBarDecorator(</p> <p> <strong><span style="color:rgb(127,0,85)">new</span></strong> VerticalScrollBarDecorator(</p> <p> <strong><span style="color:rgb(127,0,85)">new</span></strong> SimpleWindow()));</p> <p> <span style="color:rgb(63,127,95)">// print the Window's description</span></p> <p> System.<em><span style="color:rgb(0,0,192)">out</span></em>.println(decoratedWindow.getDescription());</p> <p> }</p> <p>}</p> </td> </tr> </tbody> </table> 输出结果: <table style="background-color:rgb(242,242,242)"> <tbody> <tr> <td> <p>simple window, including vertical scrollbars, including horizontal scrollbars</p> </td> </tr> </tbody> </table> 将不同的装饰区分开来,并且和原有的窗口分开,这样通过包装,我可以创建一个只带横向(纵向)滚动条的窗口,也可以创建不带滚动条的窗口,任意组合。 # 总结 # 装饰模式是不使用继承的情况下,可以动态扩展一个类,并且比继承更灵活(上面的实例)。 **分享到:** * 上一篇:[策略模式][Link 1] [1353395508_5006.png]: https://img-my.csdn.net/uploads/201211/20/1353395508_5006.png [Link 1]: http://blog.csdn.net/ghsau/article/details/8178336
相关 装饰模式 转载自:[http://blog.csdn.net/wuzhekai1985/article/details/6672614][http_blog.csdn.net_wuzhe 向右看齐/ 2022年08月11日 08:29/ 0 赞/ 191 阅读
相关 装饰模式 装饰模式 1、他所应对的问题 装饰模式主要是应对,按现有业务返回的结果,无法满足新的业务的需要了。而新的业务只是在原有结果上进行了变动。 真的这种情况 如 悠悠/ 2022年07月17日 15:26/ 0 赞/ 224 阅读
相关 装饰模式 装饰模式 装饰模式:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。 即通过不同的组合方式,可以组合出各种不同的行为。 装饰模式结构图如 浅浅的花香味﹌/ 2022年06月05日 01:25/ 0 赞/ 207 阅读
相关 装饰模式 1.使用场景: 在已有的功能上边需要动态的添加新的功能。 2.UML表示 在装饰器模式中通常用以下的几类对象: 抽象构件角色(Project):给出一个接口, 骑猪看日落/ 2022年05月31日 09:27/ 0 赞/ 249 阅读
相关 装饰模式 定义 装饰模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类模式更加灵活。 结构图 ![这里写图片描述][70] 装饰模式的简化: - 日理万妓/ 2022年05月14日 11:28/ 0 赞/ 233 阅读
相关 装饰模式 1、一个相片放入了相框,那么相框装饰了相片。相片相当于component类,相框相当于Decorator类。我们可以发现,相框里面包含一个相片,所以有了一个has-a的关系;但 àì夳堔傛蜴生んèń/ 2022年02月23日 14:40/ 0 赞/ 204 阅读
相关 装饰模式 Decorator装饰模式是一种结构型模式,它主要是解决:“过度地使用了继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩 本是古典 何须时尚/ 2022年02月23日 14:38/ 0 赞/ 218 阅读
相关 装饰模式 概述 23种设计模式之一,英文叫DecoratorPattern,中文也叫装饰模式、修饰模式。装饰模式是在不改变类文件和不使用继承的情况下,运行期动态扩展一个对象的功能。 迷南。/ 2022年02月16日 19:11/ 0 赞/ 208 阅读
相关 装饰模式 前言 装饰模式(Decorator),动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。 一、Component抽象类 绝地灬酷狼/ 2021年12月09日 00:43/ 0 赞/ 250 阅读
相关 装饰模式 有抽象类名为早餐,现在具体的食物只需继承早餐抽象类,就可以作为早餐。 具体构件类,如只有breakfast抽象类和Hamburger类,满足需求。 如果需求改变,hamb 分手后的思念是犯贱/ 2021年09月28日 07:06/ 0 赞/ 307 阅读
还没有评论,来说两句吧...