zoukankan      html  css  js  c++  java
  • 连载:面向对象的葵花宝典:思维、技能与实践(40)

    掌握了道路后,设计模式,我们将以新的方式来理解设计模式,这种方法更简单、更直观。不信?子就知道了

    =====================================================================

    DECORATOR模式(以设计模式之道来理解)

    【业务】

    假设你进入了一个信息安全管理非常严格的公司,这家公司不同意员工自行打印文档。全部的文档打印都须要交给文档打印系统统一管理。文档打印系统会记录每次打印的时间、内容、打印人员。

    。。。。

    等等。以便兴许出现故障的时候进行追查。

     

    由于公司有非常多的部门,每一个部门的安全要求并不全然一样,同一时候每一个部门关于文档打印也有自己的一些规定。

     

    我们的任务就是要开发一套可以支持整个公司文档打印需求的系统。

     

    【发现变化】

    文档打印系统面对的变化主要体如今:文档打印要求是变化的。不同的部门有不同的要求,同一个部门也可能改动自己的打印需求

     

    比如:

    A部门是一个战略规划的部门,里面的资料都非常重要,打印的时候须要在页眉位置打印“绝密”,在页脚的位置打印“密级申明”,同一时候要加上“绝密文档”的水印。

    B部门是内部培训部门,打印培训材料的时候须要在页眉位置打印“内部公开”,但不须要密级申明。同一时候加上“培训资料”的水印

    C部门是对外宣传部门,打印宣传材料的时候仅仅须要加上“公司logo”的水印。

     

    【传统方法】

    传统方法使用类继承来封装打印请求,为每一个部门创建一个打印的子类。详细演示例子代码例如以下:

    PrintTask.java -- 文档打印系统开发小组负责维护

    package com.oo.designpattern.decorator;
    
    /**
     * 打印任务类
     *
     */
    abstract public class PrintTask {
    
        abstract public void print(String text);
    
    }


    SecretPrint.java -- 文档打印系统开发小组负责维护:

    package com.oo.designpattern.decorator;
    
    /**
     * 绝密文档的打印
     *
     */
    public class SecretPrint extends PrintTask{
    
        @Override
        public void print(String text) {
            Printer.printHeader("绝密");
            Printer.printText(text);
            Printer.printFooter("本文包括绝密信息,请勿泄露!

    "); Printer.printTextWaterMark("绝密文档"); } }


    InternalPrint.java -- 文档打印系统开发小组负责维护:

    package com.oo.designpattern.decorator;
    
    /**
     * 内部公开的文档打印
     *
     */
    public class InternalPrint extends PrintTask {
    
        @Override
        public void print(String text) {
            Printer.printHeader("内部公开");
            Printer.printText(text);
            Printer.printTextWaterMark("培训资料");
        }
    
    }
    

    PublicPrint.java -- 文档打印系统开发小组负责维护:

    package com.oo.designpattern.decorator;
    
    import java.awt.Image;
    
    /**
     * 对外宣传的文档打印
     *
     */
    public class PublicPrint extends PrintTask {
    
        private Image _logo;
        @Override
        public void print(String text) {
            Printer.printText(text);
            Printer.printImgWaterMark(_logo);
        }
    
    }
    

    文档打印系统实现例如以下:

    PrintServer -- 文档打印系统开发小组负责维护

    package com.oo.designpattern.decorator;
    
    /**
     * 文档打印系统
     *
     */
    public class PrintServer {
    
        /**
         * 运行打印任务
         * @param task
         * @param text
         */
        public static void executePrintTask(PrintTask task, String text){
            log();
            task.print(text);
            audit();
        }
        
        /**
         * 记录日志
         */
        private static void log(){
            //省略详细实现代码
        }
        
        /**
         * 记录审计相关信息
         */
        private static void audit(){
            //省略详细实现代码
        }
    }

    定义好不同的打印任务后,每一个部门依据自己的须要,选择不同的任务发给文档打印系统。

    比如,A部门的打印处理例如以下:

    SecretDepartment.java  -- A部门负责维护

    package com.oo.designpattern.decorator;
    
    /**
     * A部门的打印处理
     *
     */
    public class SecretDepartment {
    
        public void print(String text){
            PrintTask task = new SecretPrint();
            
            //PrintServer即“文档打印系统”
            PrintServer.executePrintTask(task, text); 
        }
    }
    

    传统方法使用类继承来封装变化的打印需求,当面对变化时,存在例如以下问题:

    1)新增部门的时候。须要文档打印系统提供一个新的打印任务类,将导致出现大量的***Print类;

    比如:新建了一个D部门,D部门仅仅须要打印纯文本就可以,那么已有的SecretPrint、InternalPrint、PublicPrint类都无法满足需求。必须新增一个PurePrint的类;

    2)某个部门的打印需求变更的时候,须要改变已有的***Print类;

    比如:C部门希望在对外宣传材料的页眉上打印公司名称,则须要改动PublicPrint类。


    【设计模式方法】

    设计模式封装变化的方法就是Decorator模式。

    Decorator模式定义例如以下:

    “动态的给一个对象加入一些额外的职责”

     

    《设计模式》一书中关于Decorator模式的描写叙述并不非常直观,我理解Decorator模式为“通过聚合的方式将动态变化的职责组合起来”。

     

    我们详细看看Decorator模式是怎样封装变化的。

    首先,将变化的职责封装为独立的类。传统方式实现中,不同的职责是相应不同的函数调用,而设计模式中,不同的职责是不同的类;

    其次,通过聚合将变化的职责组合起来。传统方式中,不同职责的组合是通过在一个函数中写多行代码来体现的。而设计模式中,通过对象的聚合将不同职责组合起来。

    【Decorator模式结构】




    Component:定义一个对象接口(相应结构图中的operation函数),可以给这些对象动态加入职责

    ConcreteComponent:定义一个对象,这个对象是实际的Component。将被Decorator修饰

    Decorator:定义修饰对象的接口。Decorator实现的关键在于聚合了一个Component对象

    ConcreteDecorator:详细的修饰对象


    【代码实现】

    使用Decorator设计模式实现的文档打印系统代码例如以下:

    *********************类设计*****************************

     

    PrintComponent.java -- 文档打印系统开发小组负责维护

    package com.oo.designpattern.decorator2;
    
    /**
     * 打印组件的父类
     *
     */
    abstract public class PrintComponent {
    
        abstract public void print();
    }

    PrintDecorator.java -- 文档打印系统开发小组负责维护

    package com.oo.designpattern.decorator2;
    
    /**
     * 修饰的打印任务。相应Decorator模式中的Decorator
     * Decorator可以聚合ConcreteComponent或者其他Decorator
     * 这样可以使得打印任务可以嵌套运行下去。直到最后完毕全部打印任务
     *
     */
    public abstract class PrintDecorator extends PrintComponent {
    
        abstract public void print();
    }

    TextComponent.java -- 文档打印系统开发小组负责维护

    package com.oo.designpattern.decorator2;
    
    import com.oo.designpattern.decorator.Printer;
    
    /**
     * 文本打印,相应Decorator模式中的ConcreteComponent
     * 打印任务到ConcreteComponent就算真正完毕了
     *
     */
    public class TextComponent extends PrintComponent {
    
        private String _text;
        TextComponent(String text){
            this._text = text;
        }
        
        @Override
        public void print() {
            Printer.printText(this._text);
        }
    }

    HeaderDecorator.java -- 文档打印系统开发小组负责维护

    package com.oo.designpattern.decorator2;
    
    import com.oo.designpattern.decorator.Printer;
    
    /**
     * 页眉打印
     *
     */
    public class HeaderDecorator extends PrintDecorator {
    
        private PrintComponent _comp; //被修饰的打印组件
        private String _text;         //须要打印的页眉内容
        
        /**
         * 初始化的时候,必须包括其他打印组件comp。这是实现Decorator模式的前提
         * 同一时候也须要指定当前组件所需的參数。不能在print函数的參数中指定,
         * 由于每一个Decorator所需的參数是不一样的
         * @param comp
         * @param text
         */
        HeaderDecorator(PrintComponent comp, String text) {
            this._comp = comp;
            this._text = text;
        }
    
        /**
         * 打印
         */
        @Override
        public void print() {
    
            //打印的时候将当前Decorator和被修饰的Component分开,这是Decorator模式的关键
            Printer.printHeader(_text);  //打印页眉
            
            //_comp本身假设是Decorator。就会嵌套打印下去
            //_comp本身假设不是Decorator,而是ConcreteComponent,则打印任务到此结束
            _comp.print();               
        }
    }

    FooterDecorator.java

    package com.oo.designpattern.decorator2;
    
    import com.oo.designpattern.decorator.Printer;
    
    /**
     * 页脚打印。和页眉打印相似。此处省略同样的凝视代码
     *
     */
    public class FooterDecorator extends PrintDecorator {
    
        private PrintComponent _comp; 
        private String _text;         
    
        FooterDecorator(PrintComponent comp, String text) {
            this._comp = comp;
            this._text = text;
        }
    
        /**
         * 打印
         */
        @Override
        public void print() {
    
            Printer.printFooter(_text);  //打印页脚
            
            _comp.print();               
        }
    }
    

    TextWatermarkDecorator.java

    package com.oo.designpattern.decorator2;
    
    import com.oo.designpattern.decorator.Printer;
    
    /**
     * 文本水印打印。和页眉打印相似,此处省略同样的凝视代码
     *
     */
    public class TextWatermarkDecorator extends PrintDecorator{
    
        private PrintComponent _comp; 
        private String _text;         
    
        TextWatermarkDecorator(PrintComponent comp, String text) {
            this._comp = comp;
            this._text = text;
        }
    
        /**
         * 打印
         */
        @Override
        public void print() {
    
            Printer.printTextWaterMark(_text);  //打印文本水印
            
            _comp.print();               
        }
    
    }

    ImgWatermarkDecorator.java

    package com.oo.designpattern.decorator2;
    
    import java.awt.Image;
    
    import com.oo.designpattern.decorator.Printer;
    
    /**
     * 图片水印打印,和页眉打印相似,此处省略同样的凝视代码
     *
     */
    public class ImgWatermarkDecorator extends PrintDecorator {
    
        private PrintComponent _comp; 
        private static Image _logo; //图片水印仅仅能是公司logo        
    
        ImgWatermarkDecorator(PrintComponent comp) {
            this._comp = comp;
        }
    
        /**
         * 打印
         */
        @Override
        public void print() {
    
            Printer.printImgWaterMark(ImgWatermarkDecorator._logo);  //打印图片水印
            
            _comp.print();               
        }
    
    }
    

    PrintServer.java 

    package com.oo.designpattern.decorator2;
    
    public class PrintServer {
    
        /**
         * 运行打印任务
         * @param comp
         */
        public static void executePrintTask(PrintComponent comp){
            log();
            comp.print();
            audit();
        }
        
        /**
         * 记录日志
         */
        private static void log(){
            //省略详细实现代码
        }
        
        /**
         * 记录审计相关信息
         */
        private static void audit(){
            //省略详细实现代码
        }
    }
    

    *********************类使用*****************************

     

    A部门的打印处理例如以下(例如以下代码请细致阅读,特别是凝视部分):

    SecretDepartment.java  -- A部门负责维护

    package com.oo.designpattern.decorator2;
    
    /**
     * A部门的打印处理,注意与传统方法中的SecretDepartment类对照
     *
     */
    public class SecretDepartment {
    
        /**
         * 打印任务1。相应传统方式的SecretePrint类
         * @param text
         */
        public void print(String text){
            
            /**
             * 使用Decorator设计模式后。打印任务不再是一个单独的类SecretPrint类,
             * 而是通过将多个打印项目聚合成一个打印任务
             */
            PrintComponent textComp = new TextComponent(text);
            
            //注意header聚合了textComp
            PrintDecorator header = new HeaderDecorator(textComp, "绝密");  
            //注意footer聚合了header,而不是textComp,这样就行嵌套运行下去
            PrintDecorator footer = new FooterDecorator(header, "本文包括绝密信息,请勿泄露!

    "); //注意watermark聚合了footer,而不是textComp。这样就行嵌套运行下去 PrintDecorator watermark = new TextWatermarkDecorator(footer, "绝密文档"); //PrintServer即“文档打印系统”,与传统的PrintServer相比,这里不须要知道打印的text内容 //text内容已经封装到TextComponent中去了(相应代码行14行) PrintServer.executePrintTask(watermark); //注意这里传递给打印系统的是最后一个Decorator对象watermark } /** * A部门的第二个打印任务,将文本水印改为图片水印,而且不再打印页脚 * @param text */ public void print2(String text){ /** * 新增打印任务。无需文档管理系统添加新的类,仅仅要A部门自己改动代码就可以 */ PrintComponent textComp = new TextComponent(text); //注意header聚合了textComp PrintDecorator header = new HeaderDecorator(textComp, "绝密"); //注意watermark聚合了header。而不是textComp,这样就行嵌套运行下去 PrintDecorator watermark = new ImgWatermarkDecorator(header); PrintServer.executePrintTask(watermark); } }


    可以看到,使用了设计模式的方法后。打印业务的变化,可以通过相似数学上的排列组合已有的打印功能来完毕,而不再须要新的打印类了。


    ================================================ 
    转载请注明出处:http://blog.csdn.net/yunhua_lee/article/details/38865605
    ================================================ 

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    一个简单的链表结构 分类: C/C++ 数据结构与算法 2015-06-14 16:39 129人阅读 评论(1) 收藏
    整数与浮点数的二进制表示方式 分类: C/C++ 2015-06-13 15:45 54人阅读 评论(0) 收藏
    对string的一些扩展函数 分类: C/C++ 2015-06-12 15:43 170人阅读 评论(1) 收藏
    SQL常用操作 2015-06-12 12:43 20人阅读 评论(0) 收藏
    Google C++编程风格 2015-06-11 11:25 36人阅读 评论(0) 收藏
    C++头文件编译问题 分类: C/C++ 2015-06-10 15:48 32人阅读 评论(0) 收藏
    服务器TIME_WAIT和CLOSE_WAIT详解和解决办法
    解决time_wait过多的问题
    Gdb调试多进程程序
    linux查看硬件配置命令
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4629856.html
Copyright © 2011-2022 走看看