单例模式
类的构造函数如果都不是public访问属性,那么类的实例也是可以创建的。
单例模式就是这样,单例模式是一种常用的软件设计模式,其定义是单例对象的类只能允许一个实例存在。
网站的计数器,一般也是采用单例模式实现,如果你存在多个计数器,每一个用户的访问都刷新计数器的值,这样的话你的实计数的值是难以同步的。但是如果采用单例模式实现就不会存在这样的问题,而且还可以避免线程安全问题。同样多线程的线程池的设计一般也是采用单例模式,这是由于线程池需要方便对池中的线程进行控制。
步骤:构造函数私有化,提供一个全局的静态方法(全局访问点), 在类中定义一个静态指针,指向本类的变量的静态变量指针
class Singelton
{
private:
Singelton()
{
cout << "Singelton 构造函数" << endl;
}
public:
static Singelton *getInstance()
{
if (p_Singel == NULL)//如果主函数中两次获得实例,返回的其实是同一个,地址都相同的。
{
lock();//为了避免两个线程在开始时同时调用getInstance的情况。
p_Singel = new Singelton;
unlock();
}
return p_Singel;
}
static void freeInstance()
{
if (p_Singel != NULL)
{
delete p_Singel;
p_Singel = NULL;
}
}
private:
static Singelton *p_Singel;
};
Singelton * Singelton::p_Singel = NULL; //静态数据成员在类外初始化,注意初始化的时候不能再加static。只用加类型。
静态常量成员可以在类内初始化,常量成员与静态成员都不能在类内初始化。
int main()
{
Singelton *p = Singelton::getInstance();
Singelton::freeInstance();
}
https://www.cnblogs.com/dupengcheng/p/7205527.html 单例模式详解。
现在,有两个文件,每个文件中都有一个 非局部静态全局对象,其中一个对象的创建需要另一个对象的辅助,但是,绝对无法控制不同被编译单元中非局部静态对象的初始化顺序。这个时候我们可以这样解决,类似于单例模式(其实就是单例模式),首先,把每个非局部静态对象转移到函数中,声明它为static。其次,让函数返回这个对象的引用。这样,用户将通过函数调用来指明对象。换句话说,用函数内部的static对象(局部)取代了非局部静态对象。
适配器模式
假设你们公司有最近收购了一家公司,两家公司都有各自的人员管理系统,两个系统都可以获取每一个员工的姓名。
你们公司系统中接口是:getName();
被收购公司系统中接口是:getPeopleName();
现在领导要求用我们公司的系统也可以查看新收购公司的人员信息。但是很明显二者接口不一样啊。此时适配器模式就有用了。
class CompanyA{
public:
CompanyA(){}
virtual void getName()
{
cout<<"get A name"<<endl;
}
};
class CompanyB{
public:
CompanyB(){}
virtual void getPeopleName()
{
cout<<"get B name"<<endl;
}
};
class Adapters:public CompanyA,private CompanyB//其实private继承也可以改成在class Adapters中添加一个private CompanyB指针
{
public:
Adapters()
{}
void getName()
{
CompanyA::getName();
CompanyB::getPeopleName();
}
};
int main()
{
CompanyA* ca = new Adapters;
ca->getName();
}
工厂模式
简单工厂模式
有两种产品,一个工厂能够生产这两种产品,客户要产品的时候,必须指明需要哪种产品,然后工厂去制造。
这种模式,如果想要增加产品,就要修改工厂类,这样违反了开闭原则(可以扩展,但是不能修改)。
class Product{
public:
virtual void show() = 0;
};
class ProductA:public Product{
public:
void show()
{
cout<<"Product A"<<endl;
}
};
class ProductB:public Product{
public:
void show()
{
cout<<"Product B"<<endl;
}
};
class Factory{
public:
Product* create(int numProduct)
{
switch (numProduct) {
case 1:
return new ProductA;
break;
case 2:
return new ProductB;
break;
default:
break;
}
}
};
int main()
{
Factory f1,f2;
f1.create(1)->show();
f2.create(2)->show();
}
工厂方法模式
简单工厂模式,如果想要增加产品,就要修改工厂类,这样违反了开闭原则(可以扩展,但是不能修改)。
所谓工厂方法模式,是指定义一个用于创建对象的接口,让子类决定实例化哪一个类。现在有A、B两种产品,那么就开两个工厂。工厂A负责生产A产品,工厂B负责生产B产品。这时候客户不需要告诉共产生产哪种产品了,只需要告诉工厂生产就可以了。
这样,再一次增加产品的时候,只需增加一个产品类和一个工厂类就好了,不用去修改代码,只增加代码,符合开闭原则开闭原则(可以扩展,但是不能修改)。
但是,当A产品有两种型号A1、A2,B产品有两种型号B1、B2,工厂方法模式就无可奈何了,只能去修改A产品类、A工厂类、B产品类、B工厂类。
class Product{
public:
virtual void show() = 0;
};
class ProductA:public Product{
public:
void show()
{
cout<<"Product A"<<endl;
}
};
class ProductB:public Product{
public:
void show()
{
cout<<"Product B"<<endl;
}
};
class Factory{
public:
virtual Product* create() = 0;
};
class FactoryA:public Factory{
public:
Product* create()
{
return new ProductA;
}
};
class FactoryB:public Factory{
public:
Product* create()
{
return new ProductB;
}
};
int main()
{
Factory *f1 = new FactoryA;
Factory *f2 = new FactoryB;
f1->create()->show();
f2->create()->show();
}
抽象工厂模式(主要解决接口选择的问题)
当A产品有两种型号A1、A2,B产品有两种型号B1、B2,工厂方法模式就无可奈何了,只能去修改A产品类、A工厂类、B产品类。
此时需要抽象工厂模式,还是开设两家工厂,工厂A负责生产A1 、A2型号产品,B工厂负责生产B1、B2型号的产品。抽象工厂模式定义了抽象工厂类,工厂方法模式也定义了抽象工厂类,但是工厂方法模式的抽象工厂类只对应一个类型的子类,抽象工厂模式的抽象工厂类对应一系列类型的子类(多个create方法)这意味着抽象工厂模式更好的利用了工厂子类。 但是我们不去定义Product类,而改为定义1号产品类和2号产品类,若是再增加产品:
比如C1、C2,只需增加C1产品类和C2产品类,然后增加C工厂类。
如果增加了A3、B3产品,需要增加3号产品类,而且还需要修改工厂类的(不需要修改产品类,只增加)。这就是抽象工厂类的缺点。
class Product1{
public:
virtual void show() = 0;
};
class ProductA1:public Product1{
public:
void show()
{
cout<<"Product A1"<<endl;
}
};
class ProductB1:public Product1{
public:
void show()
{
cout<<"Product B1"<<endl;
}
};
class Product2{
public:
virtual void show() = 0;
};
class ProductA2:public Product2{
public:
void show()
{
cout<<"Product A2"<<endl;
}
};
class ProductB2:public Product2{
public:
void show()
{
cout<<"Product B2"<<endl;
}
};
class Factory{
public:
virtual Product1* create1() = 0;
virtual Product2* create2() = 0;
};
class FactoryA:public Factory{
public:
Product1* create1()
{
return new ProductA1;
}
Product2* create2()
{
return new ProductA2;
}
};
class FactoryB:public Factory{
public:
Product1* create1()
{
return new ProductB1;
}
Product2* create2()
{
return new ProductB2;
}
};
int main()
{
Factory* f1 = new FactoryA;//生产A产品
f1->create1()->show();
f1->create2()->show();
Factory* f2 = new FactoryB;//生产B产品
f2->create1()->show();
f2->create2()->show();
}
中介者模式
能都需要那些中介者的帮助,在地球上最大的中介者就是联合国了,它主要用来维护国际和平与安全、解决国际间经济、社会、文化和人道主义性质的问题。国与国之间的关系异常复杂,会因为各种各样的利益关系来结成盟友或者敌人,国与国之间的关系同样会随着时间、环境因为利益而发生改变。在我们软件的世界也同样如此,对象与对象之间存在着很强、复杂的关联关系,如果没有类似于联合国这样的“机构”会很容易出问题的。
对象与对象之间存在着大量的联系,导致系统结构变得复杂,如果一个对象改变,另一个对象也要跟着改变。而且系统的可扩展性低。增加一个新的对象,我们需要在其相关连的对象上面加上引用,这样就会导致系统的耦合性增高,使系统的灵活性和可扩展都降低。
如果两个类不必彼此通信,那么这两个类就不应当发生直接关联的关系。如果其中一个类需要调用另一个类中的方法,我们可以通过第三方来转发这个调用。所以对于关系比较复杂的系统,我们为了减少对象之间的关联关系,使之成为一个松耦合系统,我们就需要使用中介者模式。
以租房为例子,如果没有房屋中介,那么房客要自己找房东,而房东也要自己找房客,非常不方便。有了房屋中介机构就方便了,房东可以把要出租的房屋信息放到中介机构,而房客可以去中介机构咨询。在软件中,就是多个对象之间需要通信,如果没有中介,对象就需要知道其他对象,最坏情况下,可能需要知道所有其他对象,而有了中介对象就方便多了,对象只需与中介对象通信,而不用知道其他的对象。这就是中介者模式,下面以租房为例,给出中介者模式的UML图。
Person类 has a 中介者类,房屋中介者继承于中介者类,且房屋中介者has a 租房者、房东,租房者和房东继承于Person类。
如果再增加一个租房者或者房东,只需要在在增加一个Person子类,然后在中介者类中增加角色。
class Mediator;
class Person{
protected:
Mediator* m_mediator;//中介类
public:
virtual void setMediator(Mediator* mediator)//设置中介,意思是租房者或者房东要找的那个中介
{}
virtual void sendMessage(string message)//租房者或者房东向中介发送信息
{}
virtual void getMessage(string message)//从中介获取信息
{}
};
class Mediator{
public:
virtual void send(string message,Person* person)//person发送信息
{}
virtual void setA(Person* A)//设置其中一方
{}
virtual void setB(Person* B)//设置其中一方
{}
};
class Renter:public Person{
public:
void setMediator(Mediator* mediator)//租房者找中介
{
m_mediator = mediator;
}
void sendMessage(string message)
{
m_mediator->send(message,this);//租房者发送信息,然后中介通知房东接受信息
}
void getMessage(string message)
{
cout<<"Renter get a message:"<<message<<endl;
}
};
class LandLord:public Person{
public:
void setMediator(Mediator* mediator)//房东找中介
{
m_mediator = mediator;
}
void sendMessage(string message)
{
m_mediator->send(message,this);//房东发布信息,然后中介通知租房者接收
}
void getMessage(string message)
{
cout<<"LandLord get a message:"<<message<<endl;
}
};
class HouseMediator:public Mediator{
private:
Person* m_A;//租房者
Person* m_B;//房东
public:
void send(string message,Person* person)
{
if(person == m_A)//如果是租房者发布消息
{
m_B->getMessage(message);//房东接收消息
}
else//如果是房东发布消息
{
m_A->getMessage(message);//租房者接收消息
}
}
void setA(Person* person)//房屋中介登记租房者
{
m_A = person;
}
void setB(Person* person)//房屋中介登记房东
{
m_B = person;
}
};
int main()
{
Mediator* mediator = new HouseMediator;
Person* renter = new Renter;
Person* landlord = new LandLord;
mediator->setA(renter);//房屋中介登记租房者
mediator->setB(landlord);//房屋中介登记房东
renter->setMediator(mediator);//租房者找中介
landlord->setMediator(mediator);//房东找中介
//不管是房东还是租客,只要发布消息,就能传到中介,中介就能通知对方。
renter->sendMessage("I want a house,50x50 and has a tolit");//租房者想要房子,房东通过中介能够get这个消息
landlord->sendMessage("there is a house,80x80 and has a tolit");//房东想把房子租出去,租房者通过中介能够get这个消息
}
输出为:
LandLord get a message:I want a house,50x50 and has a tolit
Renter get a message:there is a house,80x80 and has a tolit
装饰器模式
装饰器模式能够实现动态地给对象添加功能。即从外部给对象添加相关职能。可以这样理解,比如说一个Person类,该类的操作有能吃、能睡、能跑、但假如随着人类的进化,某一天Person能飞了,能在水里游了等等,按照一般的写法是修改Person这个类,给这个类添加上能飞,能游等操作,但是这样破坏了面向对象的开放-封闭原则(对修改封闭,对拓展开发,有兴趣的可以查看相关文献),且随着人类的进化这个类就会变得越来越臃肿,越来越复杂,添加任何一个功能都必须对这个臃肿的类进行修改,出错的概率大大提升,且容易影响老功能,而装饰器模式可以解决这类问题,装饰器从外部给类添加职能,而不用去修改原始的类,拓展性好,可复用程度高。
[图片上传失败...(image-fa73bd-1560905916660)]
class Transform{//抽象具体类
public:
virtual void move() = 0;
};
class Car:public Transform{//具体类
public:
void move()
{
cout<<"I can move"<<endl;
}
};
class Changer:public Transform{//抽象装饰器类
public:
virtual void move() = 0;
protected:
Transform* t;//抽象装饰器类 has a 抽象具体类
};
class Robot:public Changer{//具体装饰器类
public:
Robot(Transform* tra)//传入抽象具体类
{
t = tra;
}
void move()//装饰具体类
{
t->move();
cout<<"I can speak"<<endl;
}
};
class Airplan:public Changer{//具体装饰器类
public:
Airplan(Transform* tra)//传入抽象具体类
{
t = tra;
}
void move()//装饰具体类
{
t->move();
cout<<"I can fly"<<endl;
}
};
int main()
{
Transform* t1 = new Car;
t1->move();
cout<<endl;
Changer* c = new Airplan(t1);
c->move();
}
代理模式
为某一个对象提供一个代理,代理控制对象的访问。
小林想追求小娟,但他不认识小娟。但他的朋友小王认识小娟,所以他通过让小王帮忙送礼物的方式追求小娟。
此时小王就是代理类,小林是RealSubject类,小王控制小林对小娟的访问。
[图片上传失败...(image-e35139-1560906028281)]
class Girl{
private:
string name;
public:
Girl(string name1)
{
name = name1;
}
string getName()
{
return name;
}
};
class Givegift{
virtual void GiveDolls() = 0;
virtual void GiveFlowers() = 0;
virtual void GiveChocolate() = 0;
};
class Puisuiter:public Givegift{
private:
Girl* m_Girl;
string name;
public:
Puisuiter(string name1,Girl* mm)
{
name = name1;
m_Girl = mm;
}
void GiveDolls()
{
cout<<name<<" Give money to "<<m_Girl->getName()<<endl;
}
void GiveFlowers()
{
cout<<name<<" Give flower to "<<m_Girl->getName()<<endl;
}
void GiveChocolate()
{
cout<<name<<" Give chocolate to "<<m_Girl->getName()<<endl;
}
};
class Proxy:public Givegift{
private:
Puisuiter* puisuiter;//代理类中 has a 真正的对象类,且代理类与真正的对象类都继承于“送礼物这个对象”。
public:
Proxy(Puisuiter* p)
{
puisuiter = p;
}
void GiveDolls()
{
puisuiter->GiveDolls();
}
void GiveFlowers()
{
puisuiter->GiveFlowers();
}
void GiveChocolate()
{
puisuiter->GiveChocolate();
}
};
int main()
{
Girl* mm = new Girl("Ma Meng");
Puisuiter* xiaolin = new Puisuiter("xiaolin",mm);
Proxy* xiaowang = new Proxy(xiaolin);
xiaowang->GiveDolls();
xiaowang->GiveFlowers();
xiaowang->GiveChocolate();
}
输出为:
xiaolin Give money to Ma Meng
xiaolin Give flower to Ma Meng
xiaolin Give chocolate to Ma Meng