zoukankan      html  css  js  c++  java
  • [读书笔记]大话设计模式(程杰)

    https://github.com/iyjhabc/Design-Pattern

    第一章:简单工厂模式

    使用一个工厂类来根据参数调用不同的函数。因此增加功能时只需改变工厂类以及新增函数即可。

    class oper
    {
    protected://使用保护成员,子类可以访问。子类不能访问私有成员
        double lhs;
        double rhs;
    public:
        double virtual getResult()=0;//纯虚函数
        void set_lhs(double lhs){this->lhs=lhs;}
        void set_rhs(double rhs){this->rhs=rhs;}
    };
    
    class oper_add:public oper
    {
    public:
        double getResult(){
            return lhs+rhs;
        }
    };
    
    class oper_minus:public oper
    {
    public:
        double getResult(){
            return lhs-rhs;
        }
    };
    
    class factory
    {
        oper *op;
    public:
        factory(){op=NULL;}
        ~factory(){if(op)delete op;}
        oper* createOperator(char oper_char){
            switch(oper_char){
                case '+':op=new oper_add;break;
                case '-':op=new oper_minus;break;
                default:cout<<"operator error"<<endl;
            }
            return op;
        }
    };
    //用户代码,计算器
    double clientCounter(double lhs,double rhs,char oper_char){
        factory fac;
        oper *op=fac.createOperator(oper_char);
        if(op==NULL)return 0;
        op->set_lhs(lhs);
        op->set_rhs(rhs);
        return op->getResult();//使用父类指针调用纯虚函数实现多态
    }

    第二章:策略模式

     使用于对同一对象使用多种算法。而且算法经常需要修改或者替换。策略模式能使用户代码与算法隔离,修改算法代码不需要修改用户代码

    class Strategy
    {
    public:
        virtual double algorithm(double cash){//虚函数,用户实现多态
            return cash;
        }
    };
    
    class StrategyA:public Strategy
    {
    public:
        double algorithm(double cash){
            return 0.8*cash;//八折
        }
    };
    
    class StrategyB:public Strategy
    {
    public:
        double algorithm(double cash){
            return cash>=100?cash-30:cash;//满100减30
        }
    };
    
    class Context
    {
        Strategy *stra;
    public:
        void loadStrategy(Strategy *s){//加载算法
            stra=s;
        }
        double getResult(double cash,int mode){
            switch(mode){
                case 0:
                    this->loadStrategy(new StrategyA);break;
                case 1:
                    this->loadStrategy(new StrategyB);break;
                default:
                    this->loadStrategy(new Strategy);
            }
            return stra->algorithm(cash);
        }
        Context(){stra=NULL;}
        ~Context(){if(stra)delete stra;}
    };
    
    //用户只需维护context类。如要增加算法,只需修改context类并给出新的算法类即可。
    //用户接触不到算法,实现了算法与用户的隔离。修改算法的时候也无需修改用户代码
    double clientFunction(double cash,int mode){
        Context context;
        return context.getResult(cash,mode);
    }

     第三章:单一职责原则

    一个类只负责一个单一的职责,只能因为特定一种业务需该改变时才需要修改类。单一职责原则使代码耦合度降低,便于维护和复用。

    第四章:开放-封闭原则

    对扩展开放,对修改封闭。新增功能时,应该以添加新的类来实现,而不是修改原有代码。

    第五章:依赖倒转原则(里氏代换原则)

    抽象不应该依赖于细节,细节依赖于抽象。针对接口与抽象类编程,而不是针对实现编程

    依赖翻转原则实现的基础:里氏代换原则-如果父类都替换成它的子类,软件不会有任何问题。例如猫狗养猪都抽象于动物类,当我们的对象从猫换成狗时,由于他们符合里氏代换原则,其他代码不必修改。

    第六章:装饰模式

    装饰模式能够为对象动态地、有序地新增一些功能。用户代码可以自主地新增功能(用户关心的是以什么顺序增添什么新功能,并不是功能的具体实现),新增功能时只需添加新的装饰实体类即可,分离了用户的核心功能与个别的装饰功能,而且每种装饰也容易复用。

    class Component
    {
    public:
        virtual void operation()=0;
    };
    //具体的对象
    class ConcreteComponent:public Component
    {
    public:
        void operation(){cout<<"I am a man"<<endl;}
    };
    //装饰类
    class Decorator:public Component
    {
    protected:
        Component *comp;
    public:
        Decorator(){comp=NULL;}
        ~Decorator(){if(comp)delete comp;}
        void set_component(Component *comp){
            this->comp=comp;
        }
        void operation(){
            if(comp)comp->operation();//关键,运行set_component所设置的行为
        }
    };
    //具体装饰类A,穿衣服
    class ConcreteDecoratorA:public Decorator
    {
    public:
        void operation(){
            Decorator::operation();//执行之前的装饰
            cout<<"dress clothes"<<endl;//本装饰类自有的行动
        }
    };
    //具体装饰类B,穿裤子
    class ConcreteDecoratorB:public Decorator
    {
    public:
        void operation(){
            Decorator::operation();//执行之前的装饰
            cout<<"dress trousers"<<endl;//本装饰类自有的行动
        }
    };
    //客户端代码,穿着函数
    void clientDress(){
        ConcreteComponent man;
        ConcreteDecoratorA *decA=new ConcreteDecoratorA;
        ConcreteDecoratorB *decB=new ConcreteDecoratorB;
        decA->set_component(&man);//decA父类的comp设置成了man,operation为man的行为
        decB->set_component(decA);//decB父类的conp设置成了decA,operation为decA的行为
        decB->operation();//先运行祖先decA的operation,而A的operation则先要运行祖先man的。
        delete decA;//因此先man->opertion,再A->opertion,再B->opertion
        delete decB;//其实就是通过set_component每层改变comp为不同的实体装饰
    }

     第七章:代理模式

    设计模式中定义: 为其他对象提供一种代理以控制对这个对象的访问(提供一个壳)。

    1) 远程代理(Remote Proxy)为一个位于不同的地址空间的对象提供一个本地的代理对象。例如网站加载大图片时可先加载包含图片位置与尺寸的代理,网站顺利显示后再下载大图片,增加网站响应速度。
    2) 虚拟代理(Virtual Proxy)根据需要创建开销很大的对象。如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的代理对象来表示,真实对象只在需要时才会被真正创建。延迟创建真实的消耗大的对象提高系统系敖律。 
    3) 保护代理(Protection Proxy)控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。
    4) 智能指引(Smart Reference)取代了简单的指针,它在访问对象时执行一些附加操作
    代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。

    //抽象父类
    class Subject
    {
    public:
        void virtual request()=0;
    };
    //真实对象类
    class Real_subject:public Subject
    {
    public:
        void request(){
            cout<<"my real request"<<endl;
        }
    };
    //代理类
    class Proxy:public Subject
    {
        Real_subject *subject;
    public:
        void request(){
            if(subject==NULL)subject=new Real_subject;//延迟创建Realsubject,用时才创建
            cout<<"I am a proxy"<<endl;//通过代理可以添加或屏蔽真实对象的功能
            subject->request();
        }
        Proxy(){subject=NULL;}
        ~Proxy(){if(subject)delete subject;}
    };
    //客户端代码
    void dosomething(Subject &subject){
        subject.request();
    }
    int main(){
        Proxy proxy;
        dosomething(proxy);
        return 0;
    }

     第八章:工厂方法模式

    与简单工厂模式的区别是,工厂变成一个抽象类,各种功能再独自继承功能工厂类。工厂类不再判断需要返回什么功能类指针,这个判断交给客户代码。如此一来新增功能时,只需增加新的方法子类,新工厂子类以及修改客户代码,不需像简单工厂模式那样修改工厂类的代码,更加符合开放-封闭原则

    代码跟简单工厂差不多:https://github.com/iyjhabc/Design-Pattern/blob/master/factory_mothod_pattern.cpp

    第九章:原型模式

    原型模式提供了一个浅复制的克隆接口,继承接口的子类可以把原型的当前状态复制到克隆体

    优点:1、克隆直接复制内存,不调用构造函数,可以快速克隆初始化开销巨大的对象;2、由于直接复制内存,克隆体跟原型的当前状态完全一致,因此可以动态地根据需要克隆,而不是新建一个初始状态的对象。

    注意:克隆提供的是浅复制,就是引用指针这种变量只是把地址直接复制到克隆体,他们指向的对象还是原型所指向的。

    //可克隆抽象父类
    class Prototype
    {
    public:
        virtual Prototype* clone()=0;
        static void freeClone(Prototype *pclone){
            delete pclone;
        }
    };
    //实际类,如简历类
    class resume:public Prototype
    {
        string name;
        int &age;//引用类型声明时必须初始化,因此必须使用初始化列表
        string experience;
    public:
        resume(string name,int &age,string experience):name(name),age(age),experience(experience){}
        void set_age(int new_age){
            this->age=new_age;
        }
        void display(){
            cout<<this->age<<endl<<this->name<<endl<<this->experience<<endl;
        }
        Prototype* clone(){//实现深复制的话只能另外new一个resume对象
                           //因为resume有引用成员变量,引用被初始化以后就不能改变引用目标
            resume *presume=(resume*)malloc(sizeof(resume));//直接浅复制,不必调用构造函数
            memcpy(presume,this,sizeof(resume));//也无视访问权限
            return presume;
        }
    };
    int main(){
        int age=25;
        resume resumeA("yjh",age,"student");
        resumeA.display();
        resumeA.display();
        resumeA.set_age(26);//动态复制,克隆的结果为最新的值
        resume *resumeB=(resume*)resumeA.clone();
        resumeB->display();
        resumeB->set_age(17);//改变B的age也是也改变了A的
        resumeB->display();
        resumeA.display();//age=17,浅复制,只复制了地址,克隆体的引用类型还是引用了原型的
        Prototype::freeClone(resumeB);
        return 0;
    }

     第十章:模板模式

    声明一个模板抽象类,把固定的操作写入模板函数中。把以后可能改变的部分声明为虚函数,让子类实现,达到代码复用。

    //抽象模板类
    class Template
    {
    public:
        virtual void altertableOperation1()=0;//模板中的可变操作部分
        virtual void altertableOperation2()=0;
        void fixOperation1(){cout<<"fixOperation1 has done"<<endl;}
        void fixOperation2(){cout<<"fixOperation2 has done"<<endl;}
        void templateMethod(){
            fixOperation1();
            altertableOperation1();//填空,把以后需要改变的地方声明为虚函数
            fixOperation2();
            altertableOperation2();
        }
    };
    //实际应用模板类A
    class concreteClassA:public Template
    {
    public:
        void altertableOperation1(){
            cout<<"classA op1 has done"<<endl;
        }
        void altertableOperation2(){
            cout<<"classA op2 has done"<<endl;
        }
    };
    //实际应用模板类B
    class concreteClassB:public Template
    {
    public:
        void altertableOperation1(){
            cout<<"classB op1 has done"<<endl;
        }
        void altertableOperation2(){
            cout<<"classB op2 has done"<<endl;
        }
    };
    //用户代码
    void client(){
        Template *p=new concreteClassA;
        p->templateMethod();
    }

     第十二章:外观模式

    给同一类子类提供一个简单的、公共的父类,组合子类的方法(如外观接口的methodA是子类1、2、4方法的叠加),给用户提供接口。用户只需知道外观接口,不必接触里面复杂的细节,使代码便于维护,降低类之间的耦合

    第十三章:建造者模式

    用于创建一些复杂的对象,对象内部的建造顺序通常是稳定的,但内部构建通常面临着复杂的变化。因此使用构造者来隔离用户与建造过程,并且使用必须重写的纯虚函数来规定每个产品的生产步骤,而细节必须被重新定制。

    class Product
    {
        string partA;
        string partB;
    public:
        void set_partA(string partA){
            this->partA=partA;
        }
        void set_partB(string partB){
            this->partB=partB;
        }
        void show_product(){
            cout<<partA<<" "<<partB<<endl;
        }
    };
    class Builder
    {
    public:
        virtual void set_partA()=0;
        virtual void set_partB()=0;
        virtual Product* get_product()=0;
    };
    class ProductBuilderA:public Builder
    {
        Product *product;
        void set_partA(){//必须重写的纯虚函数
            product->set_partA("xx");//私有的,必须利用get_product调用
        }
        void set_partB(){//确保产品必须被定制
            product->set_partB("yy");
        }
    public:
        ProductBuilderA(){
            product=new Product;
        }
        Product*get_product(){//修改此函数可以改变定制
            set_partA();//书中还通过一个director来完成定制,但我感觉集成到这里就可以了
            set_partB();
            return product;
        }
    };
    void client(){
        Builder *builder=new ProductBuilderA;
        Product *A=builder->get_product();
        A->show_product();
        delete builder;
        delete A;
    }

     第十四章:观察者模式

    观察者模式用于一个类与多个类紧密相关,一个类的状态改变了,多个类的状态也要协同改变。使用观察者模式可以把多类之间的关联解耦。使得设计更符合依赖翻转原则,即依赖于抽象。

    class Observer
    {
    public:
        virtual void update()=0;
    };
    class Subject//用户可以继承Subject来表达自己的主题
    {
        int state;
        list<Observer*> observer_list;
    public:
        void set_state(int new_state){
            this->state=new_state;
        }
        int get_state(){
            return this->state;
        }
        void add_observer(Observer* observer){
            observer_list.push_back(observer);
        }
        void del_observer(Observer* observer){
            observer_list.erase(find(observer_list.begin(),observer_list.end(),observer));
        }
        void notify(){
            for(list<Observer*>::iterator it=observer_list.begin();it!=observer_list.end();++it){
                (*it)->update();//由subject统一更新observer
            }
        }
    };
    class concreteObserverA:public Observer
    {
    public:
        void update(){
            cout<<"concreteObserverA is updated"<<endl;
        }
    };
    class concreteObserverB:public Observer
    {
    public:
        void update(){
            cout<<"concreteObserverB is updated"<<endl;
        }
    };
    void client(){
        Observer *observerA=new concreteObserverA;
        Observer *observerB=new concreteObserverB;
        Subject *subject=new Subject;
        subject->add_observer(observerA);
        subject->add_observer(observerB);
        subject->set_state(1);
        if(subject->get_state()){//如果状态改变了,所有的observer需要协同改变
            subject->notify();
        }
        delete observerA;
        delete observerB;
        delete subject;
    }
  • 相关阅读:
    apache httpd配置问题
    php文件上传进度控制模块
    “fixed” css style in mobile safari
    第八周进度表
    大白鱼团队项目计划表
    第七周进度表
    结对开发团队成员以及题目介绍
    软件工程结对作业01
    软件工程子数组求和1
    软件工程子数组求和2
  • 原文地址:https://www.cnblogs.com/iyjhabc/p/3039692.html
Copyright © 2011-2022 走看看