zoukankan      html  css  js  c++  java
  • Java设计模式(七)Decorate装饰器模式

    一、场景描述

    (一)问题

    系统中最初使用Crystal Report(水晶报表)工具生成报表,并将报表发送给客户端查看,此时定义一CrystalReport工具类即可完成水晶报表的生成工作。

    后续报表工具增加SSRS报表(SQL Server Report Service),此时可定义SSRSReport工具类完成SSRS报表的生成工作;

    并定义Report接口,重构两报表工具类实现Report接口,客户端通过接口统一调用。

    需求接着变更,报表工具需要在发送给客户端(以PDF格式)的同时,可导出一份Word可编辑版本。对此可定义CrystalReportPDF和CrystalReportWord、SSRSReportPDF、SSRSReportWord四个工具类实现相应的功能。

    需求继续变更,报表工具需要在发送给客户端(以Word格式或PDF格式)的同时,可将报表存储到文件服务器(File System)上。对此可定义CrystalReportPDF、CrystalReportPDF2FS、CrystalReportWord、CrystalReportWord2FS……。

    需求仍然在变更,报表工具增加了Fine Report(帆软报表),要求在输出的同时,存储到FTP服务器上、邮件发送给指定用户,输出格式需要Excel……

    (二)解决方案

    针对此场景,之前的办法很痛苦(通过定义类实现接口),此时可应用装饰器模式。

    报表工具一共有三种,即Crystal Report、SSRS和Fine Report,因此可定义三个类实现Report接口。

    导出为Word版本、导出为Excel版本、存储到文件系统、存储到FTP服务器上、邮件发送用户等可理解为报表工具的装饰。

    因此可以定义各种ReportGenerator的装饰类,用于给报表工具类(三种中具体的某一种)添加装饰(可以添加多种装饰,并可多次添加)。

    据此定义装饰类父类ReportGenerator,使其持有Report接口对象,并实现Report接口,至此则可对持有的对象添加装饰,并最终将装饰好的方法发布出去。

    接着为不同类型的装饰器定义类,继承父类ReportGenerator,例如定义ExportWordReport类,使其可输出Word格式报告,定义StorageReport2FTP类,使其将报表存储到FTP服务器。

    调用端,可创建某类型的报表(三种报表服务中的一种),并调用不同的装饰器类组合,实现动态扩展类功能,例如调用ExportWordReport、ExportExcelReport和StorageReport2FTP,则实现将报表输出为Word和Excel,并存储到FTP服务器。

    另外,假设有一装饰功能,发送报告生成通知给用户,发送方式有Email、短信、APP通知等,由于发送时需要对消息进行处理,因此可定义一公用的生成消息装饰类,此时装饰类可定义父子类不断继承。

    装饰器的优点是动态的扩展了类功能(相比定义具体的类去实现接口),将装饰功能抽象为装饰类,减少了实现类的数量,降低了复杂度,也更符合对象的自然情况(个人认为区分装饰类与子类的方法是,装饰可以加也可以不加,可以加一个也可以重复添加,而子类则有且仅有一个;比如吃饭时,面条、馒头、米饭作为主食,一般人是选择其中一种,则可实现为子类,而西红柿炒鸡蛋、黄瓜炒木耳等炒菜可以添加两份或三份,甚至可以要两份西红柿炒鸡蛋,因此炒菜可以作为装饰类)。

    装饰器的缺点是由于装饰的层数可以不等,因此在排查问题等方面较复杂,好比一堵墙上添了N层墙纸、刷了N多涂料,现在墙上裂了缝到底是哪里出了问题就有点难排查了。

    二、示例代码

    接口:

    package lims.designpatterndemo.decoratedemo;
    
    public interface Report {
        public String generateReport();
    }

    Crystal Report报表工具类:

    package lims.designpatterndemo.decoratedemo;
    
    public class CrystalReport implements Report {
    
        @Override
        public String generateReport() { 
            return "Generate Report using Crystal Report!";
        }
    
    }

    SSRS报表工具类:

    package lims.designpatterndemo.decoratedemo;
    
    public class SSRSReport implements Report {
    
        @Override
        public String generateReport() { 
            return "Generate Report using Sql Server Report Service!";
        } 
    }

    Fine Report报表工具类:

    package lims.designpatterndemo.decoratedemo;
    
    public class FineReport implements Report {
    
        @Override
        public String generateReport() { 
            return "Generate Report using Fine Report!";
        }
        
    }

    装饰类父类:

    package lims.designpatterndemo.decoratedemo;
    
    public class ReportGenerator implements Report {
        //持有接口
        private Report report;
        public ReportGenerator(Report report){
            this.report = report;
        }
        
        @Override
        public String generateReport() { 
            return report.generateReport();
        }
        
    }

    输出Word报告装饰类:

    package lims.designpatterndemo.decoratedemo;
    
    public class ExportWordReport extends ReportGenerator{
        public ExportWordReport(Report report) {
            super(report); 
        }
        public String generateReport() { 
            return super.generateReport() + " Export to Word Format!";
        }
    }

    输出Excel报告装饰类:

    package lims.designpatterndemo.decoratedemo;
    
    public class ExportExcelReport extends ReportGenerator{
        public ExportExcelReport(Report report) {
            super(report); 
        }
        public String generateReport() { 
            return super.generateReport() + " Export to Excel Format!";
        }
    }

    存储报告到FTP服务器装饰类:

    package lims.designpatterndemo.decoratedemo;
    
    public class StorageReport2FTP extends ReportGenerator{
        public StorageReport2FTP(Report report) {
            super(report); 
        }
        public String generateReport() { 
            return super.generateReport() + " Storage Report to FTP Server!";
        }
    }

    动态调用:

    package lims.designpatterndemo.decoratedemo;
    
    public class DecorateDemo {
        public static void main(String args[]){
            Report report = new CrystalReport();  
            report = new ExportWordReport(report);
            report = new ExportExcelReport(report);
            report = new StorageReport2FTP(report); 
            System.out.println(report.generateReport());
        } 
    }

    输出结果:

    Generate Report using Crystal Report! Export to Word Format! Export to Excel Format! Storage Report to FTP Server!

    发送通知消息装饰类:

    package lims.designpatterndemo.decoratedemo;
    
    public class SendReport extends ReportGenerator {
    
        public SendReport(Report report) {
            super(report); 
        }
        
        public String generateReport() { 
            return super.generateReport() + " Send Report!";
        }
    }

    发送消息到Email装饰类:

    package lims.designpatterndemo.decoratedemo;
    
    public class SendReport2Email extends SendReport {
    
        public SendReport2Email(Report report) {
            super(report); 
        }
        
        public String generateReport() { 
            return super.generateReport() + " send to Email!";
        }
    }

    调用测试:

    package lims.designpatterndemo.decoratedemo;
    
    public class DecorateDemo {
        public static void main(String args[]){
            Report report = new CrystalReport();  
            report = new ExportWordReport(report);
            report = new ExportExcelReport(report);
            report = new StorageReport2FTP(report); 
            report = new SendReport2Email(report);  
            System.out.println(report.generateReport());
        } 
    }

    输出结果:

    Generate Report using Crystal Report! Export to Word Format! Export to Excel Format! Storage Report to FTP Server! Send Report! send to Email!

    我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2ui9qt2awpwkg

    我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2ui9qt2awpwkg

  • 相关阅读:
    基于HTML5自定义文字背景生成QQ签名档
    一款基于jQuery外观优雅带遮罩弹出层对话框
    基于HTML5坦克大战游戏简化版
    纯CSS炫酷3D旋转立方体进度条特效
    基于CSS3 3D百叶窗图像过渡特效
    带节假日JS万年历控件代码
    基于jQuery动画二级下拉导航菜单
    基于jquery垂直缩略图切换相册
    基于jQuery左侧小图滚动右侧大图显示代码
    基于jquery仿360网站图片选项卡切换代码
  • 原文地址:https://www.cnblogs.com/mahongbiao/p/8763330.html
Copyright © 2011-2022 走看看