单例模式
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;
};
};
- 关闭对外构造与析构接口
- 静态函数getInstance创建静态对象
- 返回引用或者指针
工厂模式
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()
}
}
};
情景:
- 原先的媒体播放器只能在播放ogg格式音乐
- 有两种新的媒体播放器可以播放其他格式的音乐。
- 不改变原始接口,支持新的媒体格式
做法:
增加适配器对象,外部调用适配器接口,适配器内部调用其他对象
桥接模式
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();
}