简单工厂模式
这个模式与面向对象相关,通过面向对象的三大特征来使得程序达到可复用,易修改,易扩展的效果
本模式以写一个计算器功能,要求根据用户的输入输出相应的结果
如果没有使用任何模式代码可能如下
int main()
{
try{
std::cout<<"请输入数字A:\n";
double a;
std::cin>>a;
std::cout<<"请输入运算符号+,-,*,/:\n";
char opt;
std::cin>>opt;
//下面再类似地读入B
switch(opt)
{
case '*':
//操作
break;
case '/':
//操作,注意除法需要自己判断除数是否为0,try catch不捕捉除零错误
break;
//类似的
}
}catch(...){
std::cout<<"您的输入有误\n";
}
return 0;
}
上面的代码想要复用就必须拷贝粘贴代码,如果有多个地方要使用那多个地方就会出现重复的代码,这是在编码时应该避免的。下面通过面向的封装特性将该功能进行封装,使得其复用性大大提高
class Operation{
public:
static double GetResult(double numA,double numB,string operate){
double result = 0;
switch(operate){
case:
//实现相应功能
}
return result;
}
};
将计算这个功能给封装起来,数据的读入和检查由客户完成,这样这个代码的复用性就大大提高了,不单是现在这个程序可以用它,只要是需要通过输入得到结果的地方都可以使用
但是如果此时想要给这个功能添加一些新的计算如开根求幂等,就需要去修改switch case的结构,一方面需要将所有运算的源码交给修改人员,这不安全可能会破坏其它的运算,另一方面这样的修改会使得原来已有的运算重新编译,这是不合理的.说白了这里需要解开各个运算之间的编译耦合
下面是利用继承的方式修改的代码
class Operation{
protected:
double numA_;
double numB_;
public:
void SetA(double val);
double GetA()const;
//numB_类似有get与set
virtual double GetResult(){
double ans=0;
return ans;
}
};
class OperationAdd:public Operation{
public:
virtual double GetResult(){
return numA_ + numB_;
}
};
class OperationDiv:public Operation{
public:
virtual double GetResult()override {
if(numB_ == 0 )
throw Error;
return numA_ / numB_;
}
};
//原先其它运算符类似
class OperationSqrt:public Opearation{
if (numA_ <0)
throw Error;
return sqrt(numA_);
};
这样既增加了安全性又提高了扩展性,现在的问题就是客户必须要知道自己的运算需要调用什么样的类,但如果程序很大,对客户来说去众多类里面找到自己想要的类是很不方便的,利用多态的性质将这个任务交给一个特定的类去完成,这个类即工厂
class OperationFactory{
public:
static Operation* createOperate(char operate){
Operation* opt = nullptr;
switch(operate){
case '*':
opt = new OperationMul();
break;
case '+':
opt = new OperationAdd();
break;
//...
}
return opt;
}
};
//客户端的代码
Operation *opt;
opt = OperationFactory::createOperate('+');
opt->setA(10);
opt->setB(20);
double result = opt->GetResult();
策略模式(Stretagy)
单一职责原则(SRP)
如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会影响到其它职责的实现,这种耦合会导致脆弱的设计
开放封闭原则
对修改关闭,对扩展开放
依赖倒转原则
抽象不应该依赖底层模块,两个都应该依赖抽象。抽象不应该依赖细节,细节应该依赖于抽象。
简单地说就是应该针对接口编程而不是针对实现编程
假设在做一个大项目时需要访问数据库,常用代码会写成函数库,在上层模块中调用这些函数即可,这里就是上层模块对底层模块的依赖。但如果上层的逻辑没有变化但需要换掉访问的数据库,那就出现问题了,因为上层模块与底层是绑在一起的。
再举一个例子就是主机,CPU,内存,硬盘都是根据接口标准制造的,如果说它们根据主板实现那主板一坏其它部件都不能使用了
@startuml
(登录论坛)
(发帖子) as (tiezi_add)
usecase 删帖子 as tiezi_del
@enduml
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 2128099421@qq.com