设计模式之装饰模式

装饰模式(Decorator):

动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。

 

 

 (再来一波生硬的概念...)"Component"是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。至于ConcreteDecorator就是具体的装饰对象,起到个Component添加职责的功能。

 

案例走起

  现在公司有很多钢笔,纸张和书本,笔记本电脑等等...有桌子和书柜等...这些东西放在哪里完全由你决定...例如桌子,开始是个空桌子,用什么来"修饰"呢?我可以放钢笔也可以放纸张...接下来看看怎么实现的把!

    

 

 

 

1.根据上面的uml图,首先我们来创建家具()把,赋予它放置东西的能力(行为)

 1 package component;
 2 
 3 /**
 4  * 家具
 5  * @author DeepSleeping
 6  *
 7  */
 8 public interface Furniture {
 9 
10     /**
11      * 放置物品
12      */
13     void place();
14 }

2.接下来我们创建具体被修饰类(这里我就创建桌子table把)

 

 1 package component.concreteComponent;
 2 
 3 import component.Furniture;
 4 
 5 /**
 6  * 具体被装饰类
 7  * 桌子
 8  * @author DeepSleeping
 9  *
10  */
11 public class Table implements Furniture{
12 
13     @Override
14     public void place() {
15         System.out.println("桌子...");
16     }
17 
18 }

 

3.然后就是创建抽象修饰类把

 

 1 package decoration;
 2 
 3 import component.Furniture;
 4 
 5 /**
 6  * 装饰抽象类
 7  * @author DeepSleeping
 8  *
 9  */
10 public class Decorator implements Furniture{
11 
12     //持有被装饰类的引用
13     Furniture furniture;
14     
15     //通过构造方法传入被装饰类
16     public Decorator(Furniture furniture){
17         
18         this.furniture = furniture;
19     }
20     
21     
22     @Override
23     public void place() {
24         //调用被装饰类的方法
25         furniture.place();
26     }
27 
28 }

 

4.抽象修饰类下面自然是那些用来修饰具体被修饰类(桌子、书柜...)的具体修饰类(钢笔,纸张...)

 

 1 package decoration.concreteDecoration;
 2 
 3 import component.Furniture;
 4 import decoration.Decorator;
 5 
 6 /**
 7  * 具体修饰类(纸张)
 8  * @author DeepSleeping
 9  *
10  */
11 public class Paper extends Decorator{
12 
13     /**
14      * 因为父类Decorator中写了有参构造方法,所以无参构造方法就会没有了
15      * 子类继承父类会默认实现父类的无参构造方法,现在必须得手动实现父类中的有参构造方法...
16      * 这样就把被装饰类传进来了...
17      * @param furniture
18      */
19     public Paper(Furniture furniture) {
20         super(furniture);
21         
22     }
23 
24     /**
25      * 修饰
26      */
27     @Override
28     public void place() {
29         super.place();
30         //添加自己对应的修饰内容
31         System.out.print("放置了一张纸...\t");
32     }
33     
34 
35 }

 

 1 package decoration.concreteDecoration;
 2 
 3 import component.Furniture;
 4 import decoration.Decorator;
 5 
 6 /**
 7  * 具体修饰类(钢笔)
 8  * @author DeepSleeping
 9  *
10  */
11 public class Pen extends Decorator {
12 
13     Furniture furniture;
14     
15     public Pen(Furniture furniture) {
16         super(furniture);
17     }
18 
19     @Override
20     public void place() {
21         super.place();
22         System.out.println("放置了一支钢笔...");
23     }
24 }

5.好了,接下来就是测试了...

 

 1 package test;
 2 
 3 import component.Furniture;
 4 import component.concreteComponent.Table;
 5 import decoration.concreteDecoration.Paper;
 6 import decoration.concreteDecoration.Pen;
 7 
 8 
 9 public class TestDecorator {
10 
11     public static void main(String[] args) {
12         //实例化被装饰类的对象
13         Furniture table = new Table();
14         
15         System.out.println("******************领导A:放一张纸到桌子上...******************");
16         table = new Paper(table);    
17         table.place();
18         
19         System.out.println();
20         //再放一支钢笔在桌子上
21         System.out.println("******************领导B:放一支钢笔到桌子上...******************");
22         table = new Pen(table);
23         table.place();
24         
25         System.out.println();
26         System.out.println("******************领导C:放4支钢笔和一张纸到桌子上...******************");
27         //再放4支钢笔和一张纸在桌子上
28         table = new Pen(new Pen(new Pen(new Pen(new Paper(table)))));
29         table.place();
30     }
31 }

 

6.运行结果...

 小结:

    从上述代码中很明显可以看的出来,首先是一个空的桌子我们可以用钢笔或者纸张等来"修饰"这个桌子..

    如果需要拓展,可以继续写书柜,然后添加 书,各种修饰,书柜中想放什么动态添加就是了,非常的方便,如果有新的东西比如运来了一批海鲜,添加个海鲜类就好了,至于想放在书柜上还是书桌上由你自己来定

       不需要去修改之前的代码。

    一个软件肯定会有需求的变更拓展,这时候只要增加那些"修饰"就可以了,这里就是"开闭原则"的良好体现把!

    "开放-封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处,也就是可维护、可拓展、可复用、灵活性好。开发人员应该仅对程序中呈现出频繁变化的哪些部分做出抽象,然而,对于应用程序中的每个部分都刻意地进行抽象同样不是一个好主意。拒绝不成熟的抽象和抽象本身一样重要。"

  

学习心得:

  学习设计模式以及了解与设计有关的东西或者看看源码,对自己的思想有了一些启发把,还是挺有作用的,学习应该心平气和脚踏实地。

  不过目前呢给我的感觉还是"干嘛这么麻烦...就那样放一起不就好了,有改变的话改下代码就好了",不过在学习中,发现,到处都在强调"开闭"等,拓展性啥的。。

  基础!基础!基础!基础真的很重要!之前看代理模式完全看不懂,去补了一下多态,这里我觉得又是很好的利用了多态来进行"通信"

      多态,反射,注解,各种,还有多线程啊好多好多需要去学习和巩固深入的,漫漫长路共勉吧!

 

 

装饰模式在JAVA中的IO流就是很好的例子...):

具体的例子以及前辈运用装饰模式自定义IO流的demo在下面的参考博客中有体现...

本文参考

博客:https://blog.csdn.net/android_zyf/article/details/68343953

书籍:《大话设计模式》

 

 

 

posted @ 2018-09-24 16:18  程序员deepz  阅读(444)  评论(0编辑  收藏  举报