DesignPattern

单例模式

class Singleton
{
private:
    Singleton() {};                            // ctor hidden
    Singleton(Singleton const&) {};            // copy ctor hidden
    Singleton& operator=(Singleton const&) {}; // assign op. hidden
    ~Singleton() {};                           // dtor hidden
public:
    static Singleton& getInstance()
    {
        static Singleton obj;
        return obj;
    };
};

  1. 关闭对外构造与析构接口
  2. 静态函数getInstance创建静态对象
  3. 返回引用或者指针

工厂模式

class bird
{
    virtual void fly()=0;
}
class swallow : public bird
{
    virtual viod fly()
    {
        **************
    }
}

class goose : public bird
{
    virtual viod fly()
    {
        **************
    }
}

class sparrow : public bird
{
    virtual viod fly()
    {
        **************
    }
}

class birdFactory
{
    bird* createBird(int bird_type)
    {
        if(bird_type==sparrow)
        {
           auto r= new sparrow();
           return r;
        }
         if(bird_type==goose)
        {
           auto r= new swallow();
           return r;
        }
         if(bird_type==goose)
        {
           auto r= new goose();
           return r;
        }
    }
}



int main()
{
    auto factory fct=new birdFactory();
    auto swallow=fct.create("swallow")));
    auto goose=fct.create("goose");
    auto sparrow=fct.create("sparrow");
    swallow.fly();
    goose.fly();
    sparrow.fly();
    *****************
    return 0;
}

优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。

缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

使用场景: 1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3、设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口。

注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

组合模式

class Employee
{
public:
    string name;
    vector<Employee*> subordinates;
    void addsub() {*******}
    void remove() {********}

private:
}

int main()
{
    Employee* CEO = new Employee("John", "CEO");

    Employee* headSales = new Employee("Robert", "Head Sales");

    Employee* headMarketing = new Employee("Michel", "Head Marketing");

    Employee* clerk1 = new Employee("Laura", "Marketing");
    Employee* clerk2 = new Employee("Bob", "Marketing");

    Employee* salesExecutive1 = new Employee("Richard", "Sales");
    Employee* salesExecutive2 = new Employee("Rob", "Sales");
    CEO->add(headSales);
    CEO->add(headMarketing);

    headSales->add(salesExecutive1);
    headSales->add(salesExecutive2);

    headMarketing->add(clerk1);
    headMarketing->add(clerk2);
}

最典型的就是数据结构中的树形结构
关键代码:树枝内部组合该接口,并且含有内部属性 List,里面放 Component。
优点: 1、高层模块调用简单。 2、节点自由增加。
缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
使用场景:部分、整体场景,如树形菜单,文件、文件夹的管理。

适配器模式

class mp3player :public media
{
public:
    virtual void play();
};

class wavpalyer :public media
{
public:
    virtual void play();
};


class adaptor
{
public:
    media m;
    adaptor(music)
    {
        if (music == "mp3")
            m = new mp3player();
        if (music == "wav")
            m = new wavpalyer();
    }
    void play()
    {
        m.play();
    }
};

//play basic ogg format
class mediaplayer
{
    adaptor *adp;
public:
    void play()
    {
        if (music = "ogg")
        {
            //origin paly operation
        }
        else                        //new type music
        {
            adp = new adaptor(music);
            adp.play()
        }
    }
};

情景:

  1. 原先的媒体播放器只能在播放ogg格式音乐
  2. 有两种新的媒体播放器可以播放其他格式的音乐。
  3. 不改变原始接口,支持新的媒体格式

做法:
增加适配器对象,外部调用适配器接口,适配器内部调用其他对象

桥接模式

class draw
{
    virtual void draw() = 0;
};

class drawRed:public draw
{
    virtual void draw()
    {
        set red
    }
};

class drawGreen:public draw
{
    virtual void draw()
    {
        set green
    }
};


class shape
{
    draw* d;
    void setdraw(draw* d)
    {
        this->d = d;
    }
};
class circle : class shape
{

};

class square : class shape
{

};

int main()
{
    shape c = new circle(); //red circle
    c->setdraw(new drawRed());
    shape s = new square(); //green square
    c->setdraw(new drawGreen());
}

情景:
设计红绿圈与红绿方块

将接口变为其中一个对象成员、使其能够自由搭配,避免创建以下众多的类,难以维护

  • redsquare()
  • greensquare()
  • redcircle()
  • greencircle()

命令模式

class command
{
    virtual void excute() = 0;
};

class commandA :public command
{
    virtual void excute()
    {
        *****A
    }
};

class commandB :public command
{
    virtual void excute()
    {
        *****B
    }
};

class Invoker
{
    vector<command*> allcommands;
public:
    void addCommand(command* c)
    {
        allcommands.push_back(c);
    }
    void excuteall()
    {
        for (auto p : allcommands)
        {
            p->excute();
        }
    }
};


int main()
{
    Invoker i;
    i.addCommand(new commandA()); //添加A命令
    i.addCommand(new commandB()); //添加B命令
    i.excuteall();
}

将命令封装成一个对象,所有命令类都继承自一个抽象类,然后通过invoker类去添加与执行命令
优点: 1、降低了系统耦合度。 2、新的命令可以很容易添加到系统中去。
缺点: 使用命令模式可能会导致某些系统有过多的具体命令类。
使用场景: 认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令。 2、模拟 CMD。

观察者模式

class person
{
    string name;
    .............
    void say(){}
}
class subject
{
    int state;
    vector<person> allsubjector;
    void attach(person)
    {
        attach.push_back(person)
    }
    void notify()
    {
        for(auto p:person)
        {
            p.say();
        }
    }
    void changestate()
    {
        state = false;
        notify();
    }
}


int main()
{
    person p1,p2,p3;
    subject s;
    s.attach(p1); //增加订阅者
    s.attach(p2);
    s.attach(p3);
    s.changestate();//被观察者一旦状态改变,就会通知所有的订阅者
}

被观察者状态发生改变,会自动通知观察者

空对象模式

class object
{
    int value;
public:
    virtual getname() = 0;
};

class realobject :public object
{
public:
    void get()
    {
        cout << value;
    }
};

class nullobject :public object
{
public:
    void get()
    {
        cout << "NULL object";
    }
};

class objectFactory
{
public:
    object createobject(int id)
    {
        if (id < 0)
            return nullobject();
        else
            return realobject();
    }

};

int main()
{
    objectFactory f;
    f.createobject(1).getname();
    f.createobject(2).getname();
    f.createobject(3).getname();
    f.createobject(-1).getname();
    return 0;
}

方法: 一个空对象取代 NULL 对象(可以提供默认行为,也可以不进行任何操作)实例的检查,给使用者降低犯错的概率。

外观模式

class SubSystem_1
{
public:
    operation(){}
}

class SubSystem_2
{
public:
    operation(){}
}

class SubSystem_3
{
public:
    operation(){}
}

class Facade
{
public:
    SubSystem_1 *s1;
    SubSystem_2 *s2;
    SubSystem_3 *s3;
    Facade()
    {
        s1=new SubSystem_1();
        s2=new SubSystem_2();
        s3=new SubSystem_3();
    }
    operation()
    {
        s1->operation();
        s2->operation();
        s3->operation();
    }
}
int main()
{
    Facade f;
    f.operation();
}

外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

装饰器模式

增加若干种新装饰

class shape
{
    string s;
    virtual public void draw()
    {
        cout<<s;
    }
}

class square :public shape
{
public:
    square()
    {
        s="square";
    }
}
class circle :public shape
{
 pubic:
    circle()
    {
        s="circle";
    }
}

class decorator :public shape  //所有装饰类都继承此类
{
}

class reddecrator :public decorator
{
public:
    public reddecorator(shape* decoratedShape):shape(decoratedShape)
    {
        this.s+="red";   //new content
    }
}

class greendecrator :public decorator
{
public:
    public greendecorator(shape* decoratedShape):shape(decoratedShape)
    {
         this.s+="green";  //new content
    }
}


int main()
{
    shape* s=new square();
    shape* c=new circle();
    shape* red_s=new reddecorator(s);
    red_s->draw();
    shape* green_c=new green_decorator(c);
    green_c->draw();


}

模板模式

class game
{
public:
    virutal void start()=0;
    virutal void display()=0;
    virutal void end()=0;
};

class racecar: public game
{
public:
    virutal void start()
    {
        cout<<"racecar1";
    };
    virutal void display()
    {
        cout<<"racecar2";
    };
    virutal void end()
    {
        cout<<"racecar3";
    };
};

class football:public game
{
public:
    virutal void start()
    {
        cout<<"football1";
    };
    virutal void display()
    {
        cout<<"football2";
    };
    virutal void end()
    {
        cout<<"football3";
    };
};

int main()
{
    game g1=new football();
    g1.start();
    g1.display();
    g1.end();

    game g2=new racecar();
    g2.start();
    g2.display();
    g2.end();
    return 0;
}

最基础的运行时多态,接口类定义了相关的接口,子类实现具体的行为。

状态模式

class State
{
public:
    virtual void excute()=0;
};

class RUNState :public State
{
public:
    virtual void excute()
    {
        cout<<"RUNING...";
    }
};

class OFFState :public State
{
public:
    virtual void excute()
    {
        cout<<"SHUTDOWN...";
    }
};

class Context
{
    State* s;
public:
    void changeState(State* s)
    {
        this->s=s;
    }
    void excute()
    {
        s->excute();
    }
};

int main()
{
    Context con;
    con.changeState(new RUNState());
    con.excute();
    con.changeState(new OFFState());
    con.excute();
    return 0;
}

state中有相关的实现流程。
Context中包含了一个state
外部通过context的接口,切换不同的状态,并执行相关的内容。

享元模式

当创建大量对象时,防止重复创建已有对象,减少内存占用


class CAR
{
    string id;
    void Show()
    {
        cout<<id<<endl;
    }
}

class Factory
{
    map<string,CAR*> m;
public:
    CAR* create(string s)
    {
        auto p= m.find(s);
        if(p!=m.end()) //check whether exist
        {
            auto new_car=new CAR(s);
            map.insert(make_pair(s,new_car));
            return new_car;
        }
        else
        {
            return p->second;
        }
    }

};

int main()
{
    Factory f;
    f.create("1").show();
    f.create("2").show();
    f.create("1").show(); //won't create a new object, share the previous one.
    return 0;
}

责任链模式

定义:使多个对象都有机会处理同一个请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
使用举例:不同级别的日志记录,过滤器等



class Logger
{
    Logger* p_next;
    int log_level;
public:
    virtual print(int cur_level, string s)=0;
    void printNext(int cur_level, string s)
    {
        if(NULL!=p_next)
        {
            p_next->print(cur_level,s);
        }
    }
}

class ErrLog : public Logger
{
public:
    Errlog(Logger* p_next)
    {
        this->loglevel=3;
        this->p_next=p_next;
    }
    }
    void print(int cur_level, string s)
    {
        if(cur_level<=log_level)
        {
            cout<<"[error]"<<s<<endl;
        }
        printNext();
    }
}

class WarnLog : public Logger
{
public:
    Warnlog(Logger* p_next)
    {
        this->loglevel=2;
        this->p_next=p_next;
    }
    }
    void print(int cur_level, string s)
    {
        if(cur_level<=log_level)
        {
            cout<<"[Warn]"<<s<<endl;
        }
        printNext();
    }
}
class InfoLog : public Logger
{
public:
    Infolog(Logger* p_next)
    {
        this->loglevel=1;
        this->p_next=p_next;
    }
    }
    void print(int cur_level, string s)
    {
        if(cur_level<=log_level)
        {
            cout<<"[Info]"<<s<<endl;
        }
        printNext();
    }
}


Logger* createLogger()
{
    //这里也可以不使用继承,直接在基类上,但这种做法符合开闭原则,更加利于后期扩展
    Logger err = new ErrLog(NULL);
    Logger warn = new WarnLog(err);
    Logger  info = new InfoLog(warn);
    return info;
}

void main()
{
    Logger l = new create();
    l->print(ERROR,"xxx");  // print error info only.
    l->print(WARN,"xxx");  // print warn and error info.
    l->print(INFO,"xxx");  //print all levels info.
 }

解释器模式

解释器模式(Interpreter),给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

举例:自定义一个计算器

class Context
{
    int sum=0;
public:
    void show()
    {
        cout<<sum;
    }
}

class Expression
{
public:
  virtual interpret(Context* c)=0;
}

class AddExpression : public Expression
{
public:
  virtual interpret(Context* c)
  {
      c.sum++;
  }
}


class SubExpression : public Expression
{
public:
  virtual interpret(Context* c)
  {
      c.sum--;
  }
}

class SquareExpression : public Expression
{
public:
  virtual interpret(Context* c)
  {
      c.sum*=c.sum;
  }
}

void main()
{
    Context c= new Context();
    Expression add =new AddExpression();
    Expression sub =new SubExpression();
    Expression square =new SquareExpression();
    //let each interpreter interpret the context
    //((x+1)²-1)²
    add.interpret(c);
    square.interpret(c);
    sub.interpret(c);
    square.interpret(c);
    //context show
    c.show();
}

猜你喜欢

转载自blog.csdn.net/lugaoyong/article/details/87890183