情景:小王想送小李洋娃娃和鲜花,但是不好意思直接送,所以让小陈来帮忙。
//女孩类
class SchoolGirl {
private:
string name;
public:
void setName(string name)
{
this->name = name;
}
string getName()const {
return this->name;
}
};
//小王
class Pursuit {
public:
Pursuit(SchoolGirl *mm)
{
this->mm = mm;
}
void GiveDolls()
{
cout << mm->getName() << "送你洋娃娃" << endl;
}
void GiveFlowers()
{
cout << mm->getName() << "送你鲜花" << endl;
}
private:
SchoolGirl *mm;
};
//main
int main()
{
SchoolGirl* L = new SchoolGirl();
L->setName("小李");
Pursuit* ZZ = new Pursuit(L);
ZZ->GiveDolls();
ZZ->GiveFlowers();
return 0;
}
这样写就相当于小王自己直接送给小李,并没有使用带代理。
//定义接口
__interface GiveFift
{
void GiveDolls();
void GiveFlowers();
};
//代理类
class Proxy :public GiveFift{
private:
Pursuit *gg;
public:
Proxy(SchoolGirl* mm)
{
gg = new Pursuit(mm);
}
void GiveDolls()
{
gg->GiveDolls();
}
void GiveFlowers()
{
gg->GiveFlowers();
}
};
使用
SchoolGirl* L = new SchoolGirl();
L->setName("小小");
Proxy* XC = new Proxy(L);
XC->GiveDolls();
XC->GiveFlowers();
return 0;
代理模式:为其他对象提供一种代理以控制对这个对象的访问
//接口类
class Subject
{
public:
virtual void Request() = 0;
};
//真实请求
class RealSubject : Subject
{
public:
void Request()
{
cout << "真实的请求" << endl;
}
};
//第三方代理
class Proxy_ :Subject {
public:
void Request()
{
if(realSubject == nullptr)
{
realSubject = new RealSubject();
}
realSubject->Request();
}
private:
RealSubject *realSubject;
};
//调用
Proxy_* proxy = new Proxy_();
proxy->Request();
代理模式一般用在什么场合呢?
//操作对象类
class Operation {
public:
void setNumberA(double val){numberA = val;}
void setNumberB(double val){numberB = val;}
double getNumberA() const{return numberA;}
double getNumberB() const{return numberB;}
virtual double GetResult() = 0;
private:
double numberA, numberB;
};
//工厂类
class IFactory
{
public:
virtual Operation *CreateOperation() = 0;
};
//加法类
class OperationAdd :public Operation {
public:
double GetResult()
{
double result = 0;
result = getNumberA() + getNumberB();
return result;
}
};
//加法类工厂
class AddFactory :public IFactory {
public:
Operation *CreateOperation(){
return new OperationAdd();
}
};
//main
IFactory* operFactory = new AddFactory();
Operation *oper = operFactory->CreateOperation();
oper->setNumberA(1);
oper->setNumberB(2);
double result = oper->GetResult();
cout << "result " << result << endl;
在简单工厂里,如果需要加一个减法功能,则先加一个减法类,然后去更改工厂的方法,在“Case”语句里判断,但是现在用了工厂方法,加减法类没有问题,再加相关的工厂类,这也没有问题,但是还要去改客户端,这不等于不但没有简化难度,反而增加了很多类和方法,把复杂性增加了。
简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖
就像计算器,让客户端不用管改用哪个类的实例,只需要把“+”给工厂,工厂自动就给出了相应的实例,客户端只要去做运算就可以了,不同的实例会实现不同的运算。但问题就在这里,如果要加一个减法的功能,我们是一定需要给运算工厂类的方法里加“Case”分支条件,修改原有的类?这就等于说,我们不但对扩展开放了,对修改也开放了,这就违背了开放-封闭原则。
工厂方法模式定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类
既然工厂类与分支耦合,那么就对它下手,根据依赖倒转原则,把工厂类抽象出一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法。然后,所有的要生产具体类的工厂,就去实现这个接口,这样,一个简单工厂模式的工厂类,变成了一个工厂抽象接口和多个具体生成对象的工厂,于是,我们要增加其他运算规则,就不需要更改原有的工厂类,只需要增加此功能的运算类和对应的工厂类就可以了。
工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行,你想要加功能,本来是改工厂类的, 而现在是修改客户端。
//简历类
class Resume {
private:
string name;
string sex;
string age;
public:
Resume(string name)
{
this->name = name;
}
void SetPersonalInfo(string sex, string age)
{
this->sex = sex;
this->age = age;
}
void Display()
{
cout << "name " << name << " age " << age << " sex " << sex << endl;
}
};
//main
Resume* a = new Resume("小王");
a->SetPersonalInfo("男", "25");
a->Display();
Resume* b = new Resume("小王");
b->SetPersonalInfo("男", "25");
b->Display();
如果客户端这样编写,则多少份简历就要编写多少份,要是一个字错了,那就要改很多遍。所以,可以写成以下形式
Resume* a = new Resume("小王");
a->SetPersonalInfo("男", "25");
a->Display();
Resume* b = a;
b->Display();
原型模式(Prototype)指定创建对象的种类,并且通过拷贝这些原型创建新的对象,就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节
//原型类
class Prototype {
private:
string id;
public:
Prototype(string id)
{
this->id = id;
}
string Id()
{
return id;
}
void _SetID(string id)
{
this->id = id;
}
virtual Prototype *Clone() = 0;
};
class ConcreatePrototype :public Prototype
{
public:
ConcreatePrototype(string id):Prototype(id){}
virtual ConcreatePrototype *Clone()
{
return new ConcreatePrototype(*this);
}
void SetID(string id)
{
this->_SetID(id);
}
};
//main
ConcreatePrototype *p1 = new ConcreatePrototype("I");
ConcreatePrototype *c1 = p1->Clone();
p1->SetID("p1");
c1->SetID("c1");
cout << "p1 addr " << &p1 << " c1 addr " << &c1 << endl;
cout << p1->Id() << endl;
cout << c1->Id() << endl;
这样,如果需要更改其中一个对象,只需要对这个对象做一定的修改就行了,不会影响到其他的对象,相同的部分就不用再重复了。而且性能也会大大的提高,毕竟,每new一次,都需要执行一次构造函数,如果构造函数的执行时间很长,那么多次的执行这个初始化操作实在是太低效了。一般在初始化的信息不发生变化的情况下,克隆是最好的办法,这既隐藏了对象创建的细节,又对性能是大大的提高。等于是不用重新初始化对象,而是动态地获得对象运行时的状态