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

    书籍:《大话设计模式》

     

  • 相关阅读:
    windows内核中对于索引*4(内存)的一个反汇编知识点
    任务段与任务门
    中断门与陷阱门
    调用门
    Visual Studio 调试系列2 基本调试方法
    Visual Studio 调试系列1 Debug 与 Release 模式
    Visual Studio 调试(系列文章)
    C#各版本新增加功能(系列文章)
    C#8.0 中使用默认接口成员更新接口
    C#8.0 新增功能
  • 原文地址:https://www.cnblogs.com/deepSleeping/p/9695809.html
Copyright © 2011-2022 走看看