zoukankan      html  css  js  c++  java
  • 设计模式之装饰模式

    装饰模式(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("放置了一张纸...	");
    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

    书籍:《大话设计模式》

     

  • 相关阅读:
    cf D. Vessels
    cf C. Hamburgers
    zoj 3758 Singles' Day
    zoj 3777 Problem Arrangement
    zoj 3778 Talented Chef
    hdu 5087 Revenge of LIS II
    zoj 3785 What day is that day?
    zoj 3787 Access System
    判断给定图是否存在合法拓扑排序
    树-堆结构练习——合并果子之哈夫曼树
  • 原文地址:https://www.cnblogs.com/deepSleeping/p/9695809.html
Copyright © 2011-2022 走看看