zoukankan      html  css  js  c++  java
  • 第29章 跨战区大PK

    29.1 策略模式 VS 桥梁模式

    29.1.1 策略模式

    【编程实验】用策略模式实现邮件发送

    (1)有文本和超文本两种格式的邮件,将这两种格式封装成两种不同的发送策略

    (2)文本邮件和超文本邮件分别是两种不同格式的邮件的封装。MailServer是一个环境角色,它接收一个MailTemplate对象,并通过sendMail方法将邮件发送出去。

    //跨战区大PK——策略模式和桥接模式
    //实例:用策略模式实现邮件发送
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    //抽象邮件
    class MailTemplate
    {
    protected:
        string from;   //邮件发件人
        string to;      //收件人
        string subject; //邮件标题
    protected:
        string context; //邮件内容
    public:
        MailTemplate(string from, string to,
                     string subject, string context)
        {
            this->from = from;
            this->to = to;
            this->subject = subject;
            this->context = context;
        }
    
        string getFrom(){return from;}
        void setFrom(string value){from = value;}
    
        string getTo(){return to;}
        void setTo(string value){to = value;}
    
        string getSubject(){return subject;}
        void setSubject(string value){subject = value;}
    
        void setContext(string value){context = value;}
        virtual  string getContext() = 0;
    };
    
    //文本邮件
    class TextMail : public MailTemplate
    {
    public:
        TextMail(string from, string to,
                string subject, string context):MailTemplate(from, to, subject, context)
        {
        }
    
        string getContext()
        {
            //文本类型设置邮件的格式为text/plain
            context = "
      Context-type: text/plain;charset=GB2312
    "
                      + context;
            //同时对邮件进行base64编码处理,这里用一句话代替
            context +=  "
    邮件格式为:文本格式";
            return context;
        }
    };
    
    //超文本邮件
    class HtmlMail : public MailTemplate
    {
    public:
        HtmlMail(string from, string to,
                string subject, string context):MailTemplate(from, to, subject, context)
        {
        }
    
        string getContext()
        {
            //超文本类型设置邮件的格式为multipart/mixed
            context = "
      Context-type: multipart/mixed;charset=GB2312
    "
                      + context;
            //同时对邮件进行HTML检查,是否有类似未关闭的标答
            context +=  "
    邮件格式为:超文本格式";
            return context;
        }
    };
    
    //邮件服务器(环境角色类)
    class MailServer
    {
    private:
        MailTemplate* mail;
    public:
        MailServer(MailTemplate& mt)
        {
            mail = &mt;
        }
    
        //发送邮件
        void sendMail()
        {
            cout << "====正在发送的邮件信息====" << endl;
            //发件人
            cout << "发件人:" << mail->getFrom()<< endl;
            //收件人
            cout << "收件人:" << mail->getTo()<< endl;
            //邮件标题
            cout << "邮件标题:" << mail->getSubject()<< endl;
            //邮件内容
            cout << "邮件内容:" << mail->getContext()<< endl;
        }
    };
    
    int main()
    {
        //创建一封超文本格式的邮件
        MailTemplate* txtMail = new HtmlMail("a@a.com", "b@b.com",
                        "外星人攻击地球了", "结局是外星人被地球人打败了!");
        //创建邮件服务器
        MailServer mailServ(*txtMail);
        //发送邮件
        mailServ.sendMail();
    
    
        return 0;
    };
    /*输出结果:
    ====正在发送的邮件信息====
    发件人:a@a.com
    收件人:b@b.com
    邮件标题:外星人攻击地球了
    邮件内容:
      Context-type: multipart/mixed;charset=GB2312
    结局是外星人被地球人打败了!
    邮件格式为:超文本格式
    */
    View Code

    29.1.2 桥梁模式

    【编程实验】用桥梁模式实现邮件发送

    (1)增加了SendMail和Postfix两种邮件服务器的实现类,他们都从MailServer继承。

    (2)这样邮件服务器与邮件模板就可以独立变化

    //跨战区大PK——策略模式和桥接模式
    //实例:用桥接模式实现邮件发送
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    //抽象邮件
    class MailTemplate
    {
    protected:
        string from;   //邮件发件人
        string to;      //收件人
        string subject; //邮件标题
    protected:
        string context; //邮件内容
    public:
        MailTemplate(string from, string to,
                     string subject, string context)
        {
            this->from = from;
            this->to = to;
            this->subject = subject;
            this->context = context;
        }
    
        string getFrom(){return from;}
        void setFrom(string value){from = value;}
    
        string getTo(){return to;}
        void setTo(string value){to = value;}
    
        string getSubject(){return subject;}
        void setSubject(string value){subject = value;}
    
        void setContext(string value){context = value;}
        virtual  string getContext() = 0;
    
        //允许增加邮件发送标志
        void add(string sendInfo)
        {
            context =sendInfo + context;
        }
    };
    
    //文本邮件
    class TextMail : public MailTemplate
    {
    public:
        TextMail(string from, string to,
                string subject, string context):MailTemplate(from, to, subject, context)
        {
        }
    
        string getContext()
        {
            //文本类型设置邮件的格式为text/plain
            context = "
    Context-type: text/plain;charset=GB2312
    "
                      + context;
            //同时对邮件进行base64编码处理,这里用一句话代替
            context +=  "
    邮件格式为:文本格式";
            return context;
        }
    };
    
    //超文本邮件
    class HtmlMail : public MailTemplate
    {
    public:
        HtmlMail(string from, string to,
                string subject, string context):MailTemplate(from, to, subject, context)
        {
        }
    
        string getContext()
        {
            //超文本类型设置邮件的格式为multipart/mixed
            context = "
    Context-type: multipart/mixed;charset=GB2312
    "
                      + context;
            //同时对邮件进行HTML检查,是否有类似未关闭的标答
            context +=  "
    邮件格式为:超文本格式";
            return context;
        }
    };
    
    //邮件服务器(相当于桥接模式的抽象化角色)
    class MailServer
    {
    protected:
        MailTemplate* mail;
    public:
        MailServer(MailTemplate& mt)
        {
            mail = &mt;
        }
    
        //发送邮件
        virtual void sendMail()
        {
            cout << "====正在发送的邮件信息====" << endl;
            //发件人
            cout << "发件人:" << mail->getFrom()<< endl;
            //收件人
            cout << "收件人:" << mail->getTo()<< endl;
            //邮件标题
            cout << "邮件标题:" << mail->getSubject()<< endl;
            //邮件内容
            cout << "邮件内容:" << mail->getContext()<< endl;
        }
    };
    
    //Postfix邮件服务器
    class Postfix : public MailServer
    {
    public:
        Postfix(MailTemplate& mt):MailServer(mt){}
    
        //修正邮件发送程序
        void sendMail()
        {
            //增加邮件服务器信息
            string context = "Received: from XXXX(unknow[xxx.xxx.xxx.xxx]) by ";
            context += "aaa.aaa.com(Postfix) with ESMTP id 8DBCD172B8
    ";
    
            mail->add(context);
            MailServer::sendMail();
        }
    };
    
    //SendMail邮件服务器
    class SendMail : public MailServer
    {
    public:
        SendMail(MailTemplate& mt):MailServer(mt){}
    
        //修正邮件发送程序
        void sendMail()
        {
            //增加邮件服务器信息
            string context = "Received: (sendmail);7 Nov 2016 10:40:00 +100
    ";
    
            mail->add(context);
            MailServer::sendMail();
        }
    };
    
    int main()
    {
        //创建一封超文本格式的邮件
        MailTemplate* txtMail = new HtmlMail("a@a.com", "b@b.com",
                        "外星人攻击地球了", "结局是外星人被地球人打败了!");
        //创建邮件服务器
        MailServer* mailServ = new Postfix(*txtMail);
        //发送邮件
        mailServ->sendMail();
    
        return 0;
    };
    /*输出结果:
    ====正在发送的邮件信息====
    发件人:a@a.com
    收件人:b@b.com
    邮件标题:外星人攻击地球了
    邮件内容:
    Context-type: multipart/mixed;charset=GB2312
    Received: from XXXX(unknow[xxx.xxx.xxx.xxx]) by aaa.aaa.com(Postfix) with ESMTP
    id 8DBCD172B8
    结局是外星人被地球人打败了!
    邮件格式为:超文本格式
    */
    View Code

    29.1.3 小结

    (1)策略模式是一个行为模式,旨在封装一系列的行为。可以把邮件的必要信息封装成一个对象,也就是一个行为,封装的格式不同,行为也就不同

    (2)桥梁模式则是解决在不破坏封装的情况下将抽象和实现部分分离,让他们可以独立变化。

    (3)策略模式使用继承和多态建立一套可以自由切换算法的模式,而桥梁模式必然有两个“桥墩”——抽象化角色和实现化角色,只要桥墩搭建好了,桥就有了。策略模式只有一个抽象角色,可以没有实现,也可以有很多实现。

    29.2 外观模式 VS 中介者模式

    29.2.1 中介者模式实现工资计算

    (1)工资与职位、税收有关,职位提升工资就会增加,同时税收也增加,反之也成立。

    (2)当税收比率增加,工资自然就减少,这三者之间两两都有关系,很适合用中介者模式

    【编程实验】中介者模式实现工资计算

     

    //跨战区大PK——中介者模式和外观模式
    //实例:用中介者模式实现工资计算
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    //***********************************************辅助接口类***************************
    //职位接口
    class IPosition
    {
    public:
        virtual void promote() = 0; //升职
        virtual void demote() = 0;  //除职
    
        virtual ~IPosition(){}
    };
    
    //工资接口
    class ISalary
    {
    public:
        //加薪
        virtual void increaseSalary() = 0;
        //减薪
        virtual void decreaseSalary() = 0;
    
        virtual ~ISalary(){}
    };
    
    //税收接口
    class ITax
    {
    public:
        //税收上升
        virtual void raise() = 0;
        //税收降低
        virtual void drop() = 0;
    
        virtual ~ITax(){}
    };
    
    //*****************************************中介者************************************************
    //抽象中介者
    class AbsMediator
    {
    public:
        virtual void up(ISalary* salary) = 0;       //工资增加
        virtual void up(ITax* tax) = 0;             //税收增加
        virtual void up(IPosition* position) = 0;   //职位上升
        virtual void down(ISalary* salary) = 0;     //工资减少
        virtual void down(ITax* tax) = 0;           //税收降低
        virtual void down(IPosition* position) = 0; //职位降低
    };
    
    //*********************************************同事类**********************************
    //抽象同事类
    class AbsColleague
    {
    protected:
        //每个同事类都对中介者非常了解
        AbsMediator* mediator;
    public:
        AbsColleague(AbsMediator* mediator)
        {
            this->mediator = mediator;
        }
    };
    
    //职位
    class Position : public AbsColleague, public IPosition
    {
    public:
        Position(AbsMediator* mediator): AbsColleague(mediator){}
    
        //职位上升
        void promote()
        {
            mediator->up(this);
        }
        //职位下降
        void demote()
        {
            mediator->down(this);
        }
    };
    
    //工资
    class Salary : public AbsColleague, public ISalary
    {
    public:
        Salary(AbsMediator* mediator):AbsColleague(mediator){}
    
        void increaseSalary()
        {
            mediator->up(this);
        }
    
        void decreaseSalary()
        {
            mediator->down(this);
        }
    };
    
    //税收
    class Tax : public AbsColleague, public ITax
    {
    public:
        Tax(AbsMediator* mediator): AbsColleague(mediator){}
    
        void raise()
        {
            mediator->up(this);
        }
    
        void drop()
        {
            mediator->down(this);
        }
    };
    
    //中介者
    class Mediator : public AbsMediator
    {
    private:
        void upSalary()
        {
            cout << "工资翻倍,乐翻天" << endl;
        }
    
        void upTax()
        {
            cout << "税收上升,为国家做贡献" << endl;
        }
    
        void upPosition()
        {
            cout << "职位上升一级,狂喜" << endl;
        }
    
        void downSalary()
        {
            cout << "经济不景气,降低工资" << endl;
        }
    
        void downTax()
        {
            cout << "税收减少,国家收入减少"  << endl;
        }
    
        void downPosition()
        {
            cout << "官降三级,比自杀还痛苦" << endl;
        }
    
    public:
        //工资增加了
        void up(ISalary* salary)
        {
            upSalary();
            upTax();
        }
    
        void up(ITax* tax)
        {
            upTax();
            downSalary();
        }
    
        void up(IPosition* position)
        {
            upPosition();
            upSalary();
            upTax();
        }
    
        void down(ISalary* salary)
        {
            downSalary();
            downTax();
        }
    
        void down(ITax* tax)
        {
            downTax();
            upSalary();
        }
    
        void down(IPosition* position)
        {
            downPosition();
            downSalary();
            downTax();
        }
    };
    
    int main()
    {
        //定义中介者
        Mediator mediator;
    
        //定义各个同事类
        IPosition* position = new Position(&mediator);
        ISalary*   salary = new Salary(&mediator);
        ITax*      tax = new Tax(&mediator);
    
        //职位上升了
        position->promote();
    
        cout << endl;
    
        //职位下降了
        position->demote();
    
        delete position;
        delete salary;
        delete tax;
    
        return 0;
    };
    /*输出结果:
    职位上升一级,狂喜
    工资翻倍,乐翻天
    税收上升,为国家做贡献
    
    官降三级,比自杀还痛苦
    经济不景气,降低工资
    税收减少,国家收入减少
    */

    29.2.2 外观模式实现工资计算

    (1)工资计算是对基本工资、月奖金、绩效、考勤、税收等因素综合计算的结果。

    (2)对于高管理层,是不希望看到中间的计算过程,他只要求传递一个人员和月份即可查询到某员工的工资,而不用关心其中复杂的计算过程,这很适合用外观模式来实现。

    【编程实验】外观模式实现工资计算

     

    //跨战区大PK——中介者模式和外观模式
    //实例:用外观模式实现工资查询
    #include <iostream>
    #include <string>
    #include <ctime>
    
    using namespace std;
    
    //考勤情况
    class Attendance
    {
        int days;
    public:
        Attendance()
        {
            srand((int)time(NULL));
            days = rand() & 31;
        }
        //得到出勤天数
        int getWorkDays(){return days;}
    };
    
    //奖金计算
    class Bonus
    {
    private:
        Attendance atte; //考勤情况
    public:
        //奖金
        int getBonus()
        {
            //获得出勤情况
            int workDays = atte.getWorkDays();
            //奖金计算模型
            int bonus = workDays * 1800 / 30;
    
            return bonus;
        }
    };
    
    //基本工资
    class BasicSalary
    {
    public:
        int getBasicSalary()
        {
            return 2000;
        }
    };
    
    //绩效
    class Performance
    {
    private:
        BasicSalary basicSalary;
    public:
        int getPerformanceValue()
        {
            //随机绩效
            int perf = rand() % 101;
    
            return basicSalary.getBasicSalary() * perf /100;
        }
    };
    
    //税收
    class Tax
    {
    public:
        //交纳税收多少
        int getTax()
        {
            //随机数量
            return rand() & 300;
        }
    };
    
    //总工资计算
    class SalaryProvider
    {
    private:
        BasicSalary salary; //基本工资
        Bonus  bonus;       //奖金
        Performance perf;   //绩效
        Tax      tax;       //税收
    
    public:
        //获得用户的总收入
        int totalSalary()
        {
            return salary.getBasicSalary() + bonus.getBonus() +
                   perf.getPerformanceValue() - tax.getTax();
        }
    };
    
    //外观类
    class HRFacade
    {
    private:
        //总工资情况
        SalaryProvider salaryProvider;
        //考勤情况
        Attendance attendance;
    public:
        //查询一个人的总收入
        int querySalary(string name)
        {
            return salaryProvider.totalSalary();
        }
    
        //查询一个员工一个月工作了多少天
        int queryWorkDays(string name)
        {
            return attendance.getWorkDays();
        }
    };
    
    int main()
    {
        //定义外观
        HRFacade facade;
    
        cout << "====外系统查询总收入====" << endl;
        int salary = facade.querySalary("张三");
        cout <<"张三1月的总收放为:" << salary <<endl;
    
        //再查询出勤天数
        cout << "====外系统查询出勤天数====" << endl;
        int workDays = facade.queryWorkDays("张三");
        cout <<"张三1月的出勤天数:" << workDays <<endl;
    
        return 0;
    };
    /*输出结果:
    ====外系统查询总收入====
    张三1月的总收放为:4000
    ====外系统查询出勤天数====
    张三1月的出勤天数:29
    */

    29.2.3 小结

    (1)功能区别

      ①外观模式只是增加了一个门面,它对子系统来说没有增加任何功能,子系统可以脱离门面而独立存在,它是以封装和隔离为主要任务。

      ②中介者模式则增加了业务功能,它把各个同事类中的原有耦合关系移到了中介者,同事类不可能脱离中介者而独立存在。

    (2)知晓状态不同

      对外观模式来说,子系统不知道有门面的存在,而对中介者来说,每个同事类都知道中介者存在,因为要依靠中介者调和同事之间的关系,它们对中介者非常了解。

    (3)封装程序不同

      外观模式是一种简单的封装,所有的请求处理者委托给子系统完成,而中介者模式则需要有一个中心,由中心协调同事类完成,并且中心本身也完成部分业务,它属于更进一步的业务功能封装。

    29.3 包装模式群大PK

    (1)包装模式群包括装饰模式、适配器模式、外观模式、代理模式、桥接模式。他们中的有些角色基本自己不干活,都是通过委托的方式对一个对象或任务转发给其它类去做。

    (2)代理模式:主要用在不希望展示一个对象内部细节的场景中,比如一个远程服务不需要把远程连接的所有细节暴露给外部模式,通过增加一个代理类,可以轻松地实现被代理类的功能封装。

    (3)装饰模式:它倡导在不改变接口的前提下为对象增强功能或添加额外的职责,就扩展性而言,它比增加子类更加灵活。

    (4)适配器模式:主要意图是转换接口,把一个对象的接口转换成另一个接口。

    (5)桥接模式:在抽象层产生耦合,解决的是自行扩展的问题,它可以使两个有耦合关系的对象互不影响地扩展。

    (6)外观模式:是一个粗粒度的封装,它提供一个方便访问子系统的接口,不具有任何的业务逻辑,仅仅是一个访问复杂系统的快速通道。没有它,子系统照样运行,有了它,只是更方便访问而己。

  • 相关阅读:
    使用Flink实现索引数据到Elasticsearch
    elasticsearch更改mapping(不停服务重建索引)
    elasticsearch篇之mapping
    Elastalert安装及使用
    基于Elastalert的安全告警剖析
    elastalert
    Apache Flink:特性、概念、组件栈、架构及原理分析
    kafka partition(分区)与 group
    用Spring构建企业Java应用程序的方法
    Authentication and Authorization in ASP.NET Web API
  • 原文地址:https://www.cnblogs.com/5iedu/p/5659517.html
Copyright © 2011-2022 走看看