[读书笔记]大话设计模式(程杰)

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;
}

 

posted @ 2013-04-24 10:45  iyjhabc  阅读(2319)  评论(0编辑  收藏  举报