定义一个用于创建类的接口,让子类决定实例化哪一个类。使得一个类的实例化得到延迟。
案例
下面是一个计算器的案例,不满足开闭原则,我们需要对它进行优化
//加法
class OperationAdd
{
private:
double _numberA;
double _numberB;
public:
OperationAdd(double a , double b):_numberA(a),_numberB(b){}
double getResult(){
return _numberA+_numberB;
}
};
//减法
class OperationSub
{
private:
double _numberA;
double _numberB;
public:
OperationSub(double a , double b):_numberA(a),_numberB(b){}
double getResult(){
return _numberA-_numberB;
}
};
//乘法
class OperationMul
{
private:
double _numberA;
double _numberB;
public:
OperationMul(double a , double b):_numberA(a),_numberB(b){}
double getResult(){
return _numberA*_numberB;
}
};
//除法
class OperationDiv
{
private:
double _numberA;
double _numberB;
public:
OperationDiv(double a , double b):_numberA(a),_numberB(b){}
double getResult(){
if(-0.0000000001<_numberB && _numberB<0.000000000001)
return 0;
return _numberA/_numberB;
}
};
步骤一
将相同的部分进行抽象
class Operation
{
protected:
double _numberA;
double _numberB;
public:
Operation(double a , double b):_numberA(a),_numberB(b){}
virtual double getResult()=0;
virtual ~Operation(){}
};
//加法
class OperationAdd :public Operation
{
public:
OperationAdd(double a , double b):Operation(a,b){}
double getResult(){
return _numberA+_numberB;
}
};
//减法
class OperationSub :public Operation
{
public:
OperationSub(double a , double b):Operation(a,b){}
double getResult(){
return _numberA-_numberB;
}
};
//乘法
class OperationMul:public Operation
{
public:
OperationMul(double a , double b):Operation(a,b){}
double getResult(){
return _numberA*_numberB;
}
};
//除法
class OperationDiv :public Operation
{
public:
OperationDiv(double a , double b):Operation(a,b){}
double getResult(){
if(-0.0000000001<_numberB && _numberB<0.000000000001)
return 0;
return _numberA/_numberB;
}
};
看一下使用的方式 Operation* op = new OperationAdd(3,5); 等号左边是抽象类,但是右边是具体的类 并不符合开闭原则。
Operation* op = new OperationAdd(3,5);//具体依赖的类
qDebug()<<op->getResult()<<endl;
我们想一下有哪些方式可以构造一个类呢?
1.new方法
2.OperationAdd opadd;
3.通过方法来返回一个类的地址。
上面三种方式中只有第三种方式是可以的。
步骤二
创建一个类可以实现Operation* op = CreateOpr;这样的表达
class Factory
{
public:
Operation * CreateOpr(){
return new OperationAdd(3,5);//具体依赖的类
};
};
根据上面的工厂类可以看出,虽然Operation* op没有直接和OperationAdd关联,但是Factory是和OperationAdd直接关联的。那么我们可以将Operation * CreateOpr()这个函数抽象为虚函数,等到运行时才去分配具体实现的对象。
步骤三
class Factory
{
public:
virtual Operation * CreateOpr() = 0;
virtual ~Factory(){}
};
class OperationAddFactory : public Factory{
Operation * CreateOpr(){
return new OperationAdd(3,5);
}
};
最终通过下面的方式使用就可以解耦合
Factory* fac = new OperationAddFactory();
Operation* op = fac->CreateOpr();
qDebug()<<op->getResult()<<endl;
缺点:解决的是单个对象的需求变化。如果需要传参的话,所有的参数必须一致。