目录
前言
1.设计模式(Design pattern)定义
一套被反复使用,多数人知晓的,代码设计经验的总结。使用设计模式的目的是为了可重用代码,让代码更容易被他人理解,保证代码的可靠性。
通俗的说,就是解决问题的方法,是前辈们归纳总结出来的便于人们理解使用,增加代码的可维护性、可复用性、可扩展性。
2.为什么要使用设计模式(使用设计模式的意义)
众所周知,一款软件是否优秀在它的设计阶段就已经决定了,软件设计的好坏,关系到最终的结果。所以开发经验是必不可少的,而设计模式恰恰是开发经验的传承于总结。
3.设计原则
设计模式的使用根本原因是为了实现代码的复用、增加可维护性。那么怎么才能实现代码复用呢?面向对象有六大原则是必不可少的。
a、单一职责原则
不要存在多于一个导致类更变的原因。通俗的说,即一个类只负责一项职责。
b、开放封闭原则
一个软件实体、类、模块或者函数就应该对扩展开放,就修改关闭。简单的就是说可以增加供能,而不允许修改功能。
c、里氏代换原则
子类型必须能够替换他们的父类型,简单就是说“父债子还”。
d、迪米特法则
一个对象应该对其他对象保持最少的了解。简单来说就是对象之间不依赖与关系来保证运行的。
e、依赖倒转原则
高层模块不应该依赖低层模块,二者都应该依赖于其抽象;抽象不应该依赖细节,细节依赖抽象。简单的说就是依赖接口编程,不要对实现编程。即只要结果不顾过程。
f、合成 /聚合复用原则
合成聚合复用原则,尽量使用合成/聚合,尽量不要使用类继承。
※耦合度:是指一程序中,模块与模块之间信息或参数依赖的程度。 低耦合度:松散耦合
4.设计模式的分类
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
1.简单工厂模式
基本简介
从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
UML图
实现方式
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪个产品类的实例(这些产品类继承自一个父类或接口)
角色及其职能
包括三种角色:工厂角色、抽象产品角色、具体产品角色
工厂角色
简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
抽象产品角色
简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
具体产品角色
是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。
优点
工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。
缺点
由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;
使用场景
工厂类负责创建的对象比较少;客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。
实例1
头文件
#pragma once
#include<iostream>
#include<string>
using namespace std;
/// <summary>
/// 运算类
/// </summary>
class Operation {
public:
Operation();
Operation(double numA, double numB);
double getNumberA() const;
void setNumberA(double numA);
double getNumberB() const;
void setNumberB(double numB);
/// <summary>
/// 虚函数、运算函数
/// </summary>
/// <returns>运算后的值</returns>
virtual double GetResult();
protected:
double _numberA;
double _numberB;
};
/// <summary>
/// 加
/// </summary>
class OperationAdd:public Operation
{
public:
OperationAdd();
OperationAdd(double numA, double numB);
/// <summary>
/// 重写父类的虚函数
/// </summary>
/// <returns>运算后的值</returns>
double GetResult();
};
/// <summary>
/// 减
/// </summary>
class OperationSub :public Operation
{
public:
OperationSub();
OperationSub(double numA, double numB);
/// <summary>
/// 重写父类的虚函数
/// </summary>
/// <returns>运算后的值</returns>
double GetResult();
};
/// <summary>
/// 乘
/// </summary>
class OperationMul :public Operation
{
public:
OperationMul();
OperationMul(double numA, double numB);
/// <summary>
/// 重写父类的虚函数
/// </summary>
/// <returns>运算后的值</returns>
double GetResult();
};
/// <summary>
/// 除
/// </summary>
class OperationDiv :public Operation
{
public:
OperationDiv();
OperationDiv(double numA, double numB);
/// <summary>
/// 重写父类的虚函数
/// </summary>
/// <returns>运算后的值</returns>
double GetResult();
};
/// <summary>
/// 乘方
/// </summary>
class OperationM :public Operation
{
public:
OperationM();
OperationM(double numA, double numB);
/// <summary>
/// 重写父类的虚函数
/// </summary>
/// <returns>运算后的值</returns>
double GetResult();
};
/// <summary>
/// 简单工厂模式:定义一个创建对象的接口、让子类自己决定实例化哪个工厂类
/// 简单运算工厂类
/// </summary>
class OperationFactory
{
public:
static Operation* createOperate(char operate);
};
源文件
#include "OperationFactory.h"
Operation::Operation()
{
this->_numberA = 0;
this->_numberB = 0;
}
Operation::Operation(double numA, double numB)
{
this->_numberA = numA;
this->_numberB = numB;
}
double Operation::getNumberA() const
{
return this->_numberA;
}
void Operation::setNumberA(double numA)
{
this->_numberA = numA;
}
double Operation::getNumberB() const
{
return this->_numberB;
}
void Operation::setNumberB(double numB)
{
this->_numberB = numB;
}
double Operation::GetResult()
{
double result = 0;
return result;
}
OperationAdd::OperationAdd() :Operation()
{
}
OperationAdd::OperationAdd(double numA, double numB):Operation(numA,numB)
{
}
double OperationAdd::GetResult()
{
double result = 0;
result = _numberA + _numberB;
return result;
}
OperationSub::OperationSub():Operation()
{
}
OperationSub::OperationSub(double numA, double numB):Operation(numA,numB)
{
}
double OperationSub::GetResult()
{
double result=0;
result = _numberA - _numberB;
return result;
}
OperationMul::OperationMul():Operation()
{
}
OperationMul::OperationMul(double numA, double numB):Operation(numA,numB)
{
}
double OperationMul::GetResult()
{
return _numberA*_numberB;
}
OperationDiv::OperationDiv():Operation()
{
}
OperationDiv::OperationDiv(double numA, double numB):Operation(numA,numB)
{
}
double OperationDiv::GetResult()
{
if (_numberB == 0) {
throw "被除数不能为0";
}
return _numberA/_numberB;
}
Operation* OperationFactory::createOperate(char operate)
{
Operation* oper = nullptr;
switch (operate)
{
case '+':
oper = new OperationAdd;
break;
case '-':
oper = new OperationSub;
break;
case '*':
oper = new OperationMul;
break;
case '/':
oper = new OperationDiv;
break;
case '^':
oper = new OperationM;
default:
break;
}
return oper;
}
OperationM::OperationM():Operation()
{
}
OperationM::OperationM(double numA, double numB):Operation(numA,numB)
{
}
double OperationM::GetResult()
{
double res = 1;
for (int i = 0; i < _numberB; i++) {
res *= _numberA;
}
return res;
}
主函数
#include<iostream>
using namespace std;
#include"OperationFactory.h"
int main(int argc, char* argv[]) {
Operation *oper= OperationFactory::createOperate('^');
oper->setNumberA(2);
oper->setNumberB(3);
double res = oper->GetResult();
cout << res << endl;
system("pause");
return 0;
}
实例2
商场促销---商场收银软件 (基于qt实现)
simpleFactory头文件
/**
* @brief 简单工厂实现
* @param
* @return
*/
#ifndef SIMPLEFACTORY_H
#define SIMPLEFACTORY_H
#include<QString>
/**
* @brief 现金收费抽象类、抽象基类
* @param
* @return
*/
class CashSuper{
public:
/**
* @brief 现金收取类的纯虚函数,收取现金
* @param 原价
* @return 当前价
*/
virtual double AcceptCash(double money)=0;
};
/**
* @brief 正常收费子类
* @param
* @return
*/
class CashNormal:public CashSuper{
public:
//正常收费,原价返回
double AcceptCash(double money) override;
};
/**
* @brief 打折收费子类
* @param
* @return
*/
class CashRebate:public CashSuper{
public:
CashRebate(double moneyRebate);//打折收费,初始化时输入折扣率
double AcceptCash(double money) override;
private:
double moneyRate=1;
};
/**
* @brief 返利收费子类,初始化时输入返利条件和返利值
* @param 返利条件moneyCondition 返利值moneyReturn
* @return
*/
class CashReturn:public CashSuper{
public:
CashReturn(double moneyCondition,double moneyReturn);
double AcceptCash(double money) override;
private:
double moneyCondition=0.0;
double moneyReturn=0.0;
};
/**
* @brief 现金收费工厂类
* @param
* @return
*/
class CashFactory{
public:
static CashSuper* CreateCashAccept(int type);
};
#endif // SIMPLEFACTORY_H
simpleFactory源文件
#include "simplefactory.h"
double CashNormal::AcceptCash(double money)
{
return money;
}
CashRebate::CashRebate(double moneyRebate)
{
if(moneyRebate>1||moneyRebate<0){
throw "rate error";
}
this->moneyRate=moneyRebate;
}
double CashRebate::AcceptCash(double money)
{
return money*moneyRate;
}
CashReturn::CashReturn(double moneyCondition, double moneyReturn)
{
this->moneyCondition=moneyCondition;
this->moneyReturn=moneyReturn;
}
double CashReturn::AcceptCash(double money)
{
double result=money;
if(money>=moneyCondition){
result=money-moneyReturn;
}
return result;
}
CashSuper* CashFactory::CreateCashAccept(int type)
{//type 现金收取工厂
CashSuper *cs=nullptr;
switch (type) {//根据条件返回相应的对象
case 0:
cs=new CashNormal();
break;
case 1:
cs=new CashReturn(300,100);
break;
case 2:
cs=new CashRebate(0.8);
break;
case 3:
cs=new CashRebate(0.5);
break;
case 4:
cs=new CashReturn (500,200);
break;
default:
break;
}
return cs;
}
客户端代码
void Widget::on_btn_ok_clicked()//点击确定槽函数
{
double total=0.00;//声明一个double变量total来计算总计
double price=ui->line_Price->text().toDouble();//lineEdit获取price
double num=ui->line_Num->text().toDouble();//lineEdit获取num
total=num*price;//获取合计
CashSuper* csuper=CashFactory::CreateCashAccept(ui->comboBox->currentIndex());
total=csuper->AcceptCash(total);
ui->listWidget->addItem("单价:"+ui->line_Price->text()+
" 数量:"+ui->line_Num->text()+
" "+ui->comboBox->currentText()+
" 合计:"+QString::number(total));//添加到啊listWidget中
ui->labShowPrice->setText(QString::number(total));//显示到lab中。
}