• 第27章 结构型模式大PK


    27.1 代理模式 VS 装饰模式

    27.1.1 代理模式

    (1)场景:客人找运动员代理要求安排运动员参加比赛

    (2)说明:代理人有控制权,可以拒绝客人的要求,也可以答应安排,甚至自己下去跑(因为有些运动员本身就作自己的代理)

    【编程实验】找代理安排运动员比赛

     

    //结构型模式大PK——代理模式和装饰模式
    //实例:找代理安排运动员比赛
    #include <iostream>
    #include <ctime>
    using namespace std;
    
    //抽象运动员
    class IRunner
    {
    public:
        virtual void run() = 0;
    
        virtual ~IRunner() {}
    };
    
    //运动员
    class Runner : public IRunner
    {
    public:
        void run()
        {
            cout << "运动员跑步,动作很潇洒" << endl;
        }
    };
    
    //代理人(也与运动员一样,实现同一接口)
    class RunnerAgent : public IRunner
    {
        Runner* runner;
    public:
        RunnerAgent(Runner* runner)
        {
            srand((int)time(NULL));
            this->runner = runner;
        }
    
        void run()
        {
            if((rand() % 2) ==0)
            {
                cout << "代理人同意安排运动员跑步" << endl;
                runner->run();
            }
            else
            {
                cout << "代理人心情不好,不安排运动员跑步" << endl;
            }
        }
    };
    
    int main()
    {
        //定义一个运动员
        Runner* runner = new Runner();
        //定义代理人
        IRunner* agent = new RunnerAgent(runner);
    
        //要求运动员跑步
        cout << "===客人找到代理要求运动员去跑步" << endl;
    
        //为演示,比如洽谈了10次
        for(int i=0; i<10; i++)
        {
            cout <<"" <<i+1 <<"次洽谈结果:";
            agent->run();
            cout << endl;
        }
    
        delete runner;
        delete agent;
    
        return 0;
    };
    View Code

    27.1.2 装饰模式

    (1)装饰模式:对类的功能进行加强

    【编程实验】安装喷气装置

     

    //结构型模式大PK——代理模式和装饰模式
    //实例:为飞机安装喷气动力装置
    #include <iostream>
    #include <ctime>
    using namespace std;
    
    //飞行接口
    class IFly
    {
    public:
        virtual void fly() = 0;
    
        virtual ~IFly() {}
    };
    
    //飞机
    class AirPlane : public IFly
    {
    public:
        void fly()
        {
            cout << "飞机正在飞行..." << endl;
        }
    };
    //JetFly
    class JetFly : public IFly
    {
        IFly* airPlane;
    public:
        JetFly(IFly* airPlane)
        {
            this->airPlane = airPlane;
        }
        void speedUp()
        {
            cout << "为飞机加装了喷气动力装置,正在加速中..." << endl;
        }
        void fly()
        {
           speedUp();
           airPlane->fly();
        }
    };
    int main()
    {
        //定义一架飞机
        IFly* airPlane = new AirPlane();
        //定义装饰类,对功能进行加强
        IFly* jet = new JetFly(airPlane);
    
        cout << "===增加功能后的飞机" << endl;
    
        jet->fly();
    
        delete jet;
        delete airPlane;
    
        return 0;
    };
    View Code

    27.1.3 最佳实践

    (1)装饰类对被装饰的类的行为没有决定权,只有增强作用。而代理可以控制对被代理人的访问。

    (2)代理模式是把当前的行为或功能委托给其他对象执行,代理类负责接口限定(如是否可以调用真实角色,一般不对被代理功能当修饰,而是保证原汁原叶的调用

    (3)装饰模式在保证接口不变的情况下加强类的功能,它保证的是被修饰对象功能比原来丰富(当然也可以减弱),但不做准入条件和准入参数的过滤

    27.1.3 最佳实践

    (1)装饰类对被装饰的类的行为没有决定权,只有增强作用。而代理可以控制对被代理人的访问。

    (2)代理模式是把当前的行为或功能委托给其他对象执行,代理类负责接口限定(如是否可以调用真实角色,一般不对被代理功能当修饰,而是保证原汁原叶的调用

    (3)装饰模式在保证接口不变的情况下加强类的功能,它保证的是被修饰对象功能比原来丰富(当然也可以减弱),但不做准入条件和准入参数的过滤

    27.2 装饰模式 VS 适配器模式

    27.2.1 用装饰模式描述丑小鸭

    (1)丑小鸭首先是一只天鹅,具备了天鹅所有的行为和属性(即它从天鹅继承而来)

    (2)只是小时候,又小、又脏,又不能飞行。随着时间推移,对其属性和行为进行加强,慢慢变成一只白天鹅。

    【编程实验】丑小鸭变小天鹅的故事

    //结构型模式大PK——装饰模式和适配器模式
    //实例:丑小鸭变小天鹅
    #include <iostream>
    #include <ctime>
    using namespace std;
    
    //天鹅接口
    class Swan
    {
    public:
        virtual void fly() = 0;  //会飞
        virtual void cry() = 0;  //会叫
        virtual void Appearance() = 0; //外观
    
        virtual ~Swan(){}
    };
    
    //丑小鸭(本质上是天鹅)
    class UglyDuckling : public Swan
    {
    public:
        //丑小鸭还比较小,不能飞
        void fly()
        {
            cout << "不能飞" <<endl;
        }
        //丑小鸭的叫声
        void cry()
        {
            cout << "叫声是克噜——克噜——克噜" << endl;
        }
    
        //丑小鸭的外形
        void Appearance()
        {
            cout << "外形是脏兮兮的白色,毛毛茸茸的大脑袋"  <<endl;
        }
    };
    
    //装饰类
    class Decorator : public Swan
    {
    private:
        Swan* swan;
    public:
        Decorator(Swan* swan)
        {
            this->swan = swan;
        }
        void fly()
        {
            swan->fly();
        }
    
        void cry()
        {
            swan->cry();
        }
    
        void Appearance()
        {
            swan->Appearance();
        }
    };
    
    //具体的装饰类(外形美化)
    class BeautifyAppearance : public Decorator
    {
    public:
        BeautifyAppearance(Swan* swan):Decorator(swan){}
    
        //外表美化处理(重写该方法)
        void Appearance()
        {
            //这里是重新实现,不再调用原来的Decorator::desAppearance()
            cout << "外表是纯白色的,非常惹人喜爱" << endl;
        }
    };
    
    //具体装饰类
    class StrongBehavior :public Decorator
    {
    public:
        StrongBehavior(Swan* swan):Decorator(swan){}
    
        //会飞行了
        void fly()
        {
            //这里是完全重新实现了被装饰类飞的功能。
            cout << "会飞行了!" << endl;
        }
    };
    
    int main()
    {
        cout <<"===很久很久以前,这里有一只丑陋的小鸭子===" << endl;
        Swan* duckling = new UglyDuckling();
    
        //展示一下小鸭
        duckling->Appearance();
        duckling->cry();
        duckling->fly();
    
        cout <<"===小鸭子终于发现自己是一只天鹅===" << endl;
        //首先外形变化
        BeautifyAppearance duckling2(duckling);
        StrongBehavior duckling3(&duckling2);
    
        duckling3.Appearance();
        duckling3.cry();
        duckling3.fly();
    
        delete duckling;
    
        return 0;
    };
    /*输出结果:
    ===很久很久以前,这里有一只丑陋的小鸭子===
    外形是脏兮兮的白色,毛毛茸茸的大脑袋
    叫声是克噜——克噜——克噜
    不能飞
    ===小鸭子终于发现自己是一只天鹅===
    外表是纯白色的,非常惹人喜爱
    叫声是克噜——克噜——克噜
    会飞行了!
    */
    View Code

    27.2.2 用适配器模式描述丑小鸭

    (1)两个接口:鸭和天鹅。而丑小鸭就相当于适配器

    (2)为了演示适配器的使用,丑小鸭本质上是天鹅,所以应该把鸭子的接口转为天鹅的接口。即鸭子的源接口,目标接口为天鹅。以便让天鹅具备小鸭的一些特点。

    【编程实验】一只与众不同的鸭子

    //结构型模式大PK——装饰模式和适配器模式
    //实例:一只与众不同的鸭子
    #include <iostream>
    #include <ctime>
    using namespace std;
    
    //天鹅接口
    class Swan
    {
    public:
        virtual void behavior() = 0;  //其他行为,会飞
        virtual void cry() = 0;  //会叫
        virtual void Appearance() = 0; //外观
    };
    
    //鸭子的接口
    class Duck
    {
    public:
        virtual void behavior() = 0;  //会游泳
        virtual void cry() = 0;  //会叫
        virtual void Appearance() = 0; //外观
    
        virtual ~Duck(){}
    };
    
    //白天鹅
    class WhiteSwan : public Swan
    {
    public:
        void cry()
        {
            cout << "叫声是克噜——克噜——克噜" << endl;
        }
        void Appearance()
        {
            cout << "外形是纯白色,惹人喜爱" << endl;
        }
        //其他行为
        void behavior()
        {
            cout << "能够飞行" << endl;
        }
    };
    
    //小鸭子
    class Duckling : public Duck
    {
    public:
        void cry()
        {
            cout << "叫声是嘎——嘎——嘎" << endl;
        }
        void Appearance()
        {
            cout << "外形是黄白相间,嘴长" << endl;
        }
    
        //描述鸭子的其他行为
        void behavior()
        {
            cout << "会游泳" << endl;
        }
    };
    
    //丑小鸭相当于适配器的角色,丑小鸭本质上是天鹅,所以应该把鸭子
    //的接口转为天鹅的接口。即鸭子的源接口,目标接口为天鹅
    class UglyDuckling : public WhiteSwan
    {
       Duck* duck;  //目标接口
    public:
        UglyDuckling(Duck* duck)
        {
            this->duck = duck;
        }
        //丑小鸭的叫声,直接从父类继承
    
        //丑小鸭的外形,直接从父类继承
    
        //其他行为
        void behavior()
        {
            //本身会飞
            WhiteSwan::behavior();
            //学会鸭子的游泳
            duck->behavior();
        }
    };
    
    int main()
    {
        cout <<"===鸭妈妈有5个孩子,其中4个都是一个模样==="<< endl;
        Duck* duck = new Duckling();
        duck->cry();
        duck->Appearance();
        duck->behavior();
    
        cout <<"===一只独特的小鸭子,模样是这样的==="<< endl;
        UglyDuckling uglyDuckling(duck);  //丑小鸭
        uglyDuckling.cry();
        uglyDuckling.Appearance();
        uglyDuckling.behavior();
    
        delete duck;
    
        return 0;
    };
    /*输出结果:
    ===鸭妈妈有5个孩子,其中4个都是一个模样===
    叫声是嘎——嘎——嘎
    外形是黄白相间,嘴长
    会游泳
    ===一只独特的小鸭子,模样是这样的===
    叫声是克噜——克噜——克噜
    外形是纯白色,惹人喜爱
    能够飞行
    会游泳
    */
    View Code

    27.2.3 最佳实践

    (1)装饰模式包装的是自己的兄弟类,隶属于同一家族(相同的父类),而适配器模式则修饰的是非血缘关系类。把一个非本家族伪装成本家族的对象,注意是伪装,因此它的本质还是不同的接口对象。

    (2)意图不同

      装饰模式的意图是加强对象的功能,而适配器模式关注的是转化,两个对象之间的接口转化

    (3)所作用的对象不同

      ①装饰模式装饰的对象必须是自己的同宗,也就是相同的父类,只要在具有相同的属性和行为情况下,才能比较行为是增加或减弱。

      ②适配器模式则必须是两个不对象接口对象,因为它着重于转换

    (4)场景不同

      ①装饰模式只要是想增强功能,都可以用。

      ②适配器模式则是一个补救模式,一般出现在系统成熟或己经构建完毕的项目中,作为一个紧急处理手段采用。

    (5)扩展性不同

      装饰模式容易扩展,如果不需要修饰某对象了,可以随时拿掉,而且装饰类也可以继续扩展。但适配器模式就不同,它在两个不同对象之间架起一座沟通的桥染,建立容易,去掉时需要从系统整体考虑是否能够撤销。

  • 相关阅读:
    固定执行计划-SQL PROFILE手工绑定
    其他典型的执行计划
    oracle-常见的执行计划(一)
    DBMS_XPLAN详细说明
    sql-查看执行计划的方法
    CBO基础概念
    webpack生产环境保留某些console.log
    提升webpack构建速度(二)
    提升webpack构建速度(一)
    【译文】更有效的调试webpack在构建时出现的错误
  • 原文地址:https://www.cnblogs.com/5iedu/p/5655921.html
Copyright © 2020-2023  润新知