面向过程通过划分功能模块,通过函数相互间的调用来实现,但需求变化时,就需要更改函数。而你改动的函数有多少的地方在调用他关联多少数据,这是很不容易弄得清楚的地方。
通过选择合适得设计模式可以提高代码的可复用性,可维护性,可扩展性以及灵活性,这些都是系统设计中非常重要的非功能性需求。
几大设计原则:
单一职责:对于一个类来说,应该仅有一个引起他变化的原因,功能要单一,降低耦合性。
开放-封闭原则:对于扩展开放,对于更改时封闭的
依赖倒转原则:高层模块不应该依赖低层模块,应该都依赖抽象;抽象不应该依赖细节,细节应该依赖抽象。
里氏替换原则:子类必须能够替换掉他们的父类;子类继承父类,所以字类拥有父类所有非私有方法。
迪米特法则:强调了类之间的松耦合。如果两个类不必彼此直接通信,那么这两个类就不应该发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
客户端和具体实现类进行解耦,不需要考虑某些对象创建过程比较复杂的情况
#include
#include
using namespace std;
// 运算父类
class Program {
private:
string numA;
string numB;
public:
Program() {}
virtual string getRes() {
return "0";
}
void setA(string A) {
this->numA = A;
}
void setB(string B) {
this->numB = B;
}
string getA() {
return this->numA;
}
string getB() {
return this->numB;
}
};
//加法类
class ProgramAdd :public Program {
public:
ProgramAdd() {}
string getRes() {
return to_string(stoi(getA()) + stoi(getB()));
}
};
//减法类
class ProgramSub :public Program {
public:
ProgramSub() {}
string getRes() {
return to_string(stoi(getA()) - stoi(getB()));
}
};
//乘法类
class ProgramMul :public Program {
public:
ProgramMul() {}
string getRes() {
return to_string(stoi(getA()) * stoi(getB()));
}
};
//除法类
class ProgramDiv :public Program {
public:
ProgramDiv() {}
string getRes() {
return to_string(stoi(getA()) / stoi(getB()));
}
};
//简单工厂类
class PragramFactory { // 增加功能时,修改工厂类,不符合开放-封闭原则
public:
Program* createOperator(char signal) {
Program *opre = nullptr;
switch (signal) {
case '+':
opre = new ProgramAdd();
break;
case '-':
opre = new ProgramSub();
case '*':
opre = new ProgramMul();
break;
case '/':
opre = new ProgramDiv();
break;
}
return opre;
}
};
//客户端
int main()
{
char signal = '+';
Program *pro = new Program;
pro = PragramFactory().createOperator(signal);
pro->setA("1");
pro->setB("2");
string res = pro->getRes();
cout << res << endl;
return 0;
}
简单工厂模式增加新功能需要修改源代码,不符合开闭原则
定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂模式使一个类的实例化延迟到其子类。
#include
using namespace std;
//抽象对象接口
class Waiter {
public:
void sweep() {
cout << "扫地" << endl;
}
void wash() {
cout << "洗碗" << endl;
}
void send() {
cout << "送菜" << endl;
}
};
//具体对象接口
class WaiterA :public Waiter {};
class WaiterB:public Waiter{};
//抽象工厂类
class WaiterFactory {
public:
virtual Waiter* createWaiter() = 0;
};
//具体工厂类
class WaiterAFactory :public WaiterFactory {
public:
Waiter* createWaiter() {
return new WaiterA;
}
};
//具体工厂类
class WaiterBFactory :public WaiterFactory {
public:
Waiter* createWaiter() {
return new WaiterB;
}
};
int main() {
//想要实现什么具体对象,就new一个什么工厂
WaiterFactory* factory = new WaiterAFactory;
//w1为WaiterA类对象
Waiter* w1 = factory->createWaiter();
w1->send();
w1->sweep();
w1->wash();
return 0;
}
工厂方法模式保持简单工厂的优点,克服了其缺点,但是由于没加一个具体对象类就要加一个相应的工厂类。
提供一个创建一系列或相关依赖对象的接口,而无需指定他们具体的类。很容易交换不同的产品,他让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操作实例,产品的具体类名也被具体工厂的实现分离。
#include
using namespace std;
class User {
private:
int id;
string name;
public:
};
class Department {
private:
int did;
string dname;
public:
};
//用户表抽象类
class Iuser {
public:
virtual void insert(User* user) = 0;
virtual User* getUser(int id) = 0;
};
//sql用户具体类
class SqlserverUser :public Iuser {
public:
void insert(User* user) {
cout << "在SQL Server 中给User表增加一条记录\n";
}
User* getUser(int id) {
cout << "在SQL Server 中查到User一条记录\n";
return nullptr;
}
};
//access用户具体类
class AccessUser :public Iuser {
void insert(User* user) {
cout << "在Acess Server 中给User表增加一条记录\n";
}
User* getUser(int id) {
cout << "在Acess Server 中查到User一条记录\n";
return nullptr;
}
};
//部门抽象类
class IdDepartment {
public:
virtual void insert(Department* dept) = 0;
virtual User* getUser(int id) = 0;
};
//sql部门具体类
class SqlserverDepartment :public IdDepartment {
public:
void insert(Department* dept) {
cout << "在SQL Server 中给Department表增加一条记录\n";
}
User* getUser(int id) {
cout << "在SQL Server 中查到Department一条记录\n";
return nullptr;
}
};
//access部门具体类
class AccessDepartment :public IdDepartment {
void insert(Department* deptr) {
cout << "在Acess Server 中给Department表增加一条记录\n";
}
User* getUser(int id) {
cout << "在Acess Server 中查到Department一条记录\n";
return nullptr;
}
};
//抽象工厂类
class IFactory {
public:
virtual Iuser* CreateUser() = 0;
virtual IdDepartment* CreateDepartment() = 0;
};
//sql具体工厂类
class SqlserverFactory :public IFactory {
public:
Iuser* CreateUser() {
return new SqlserverUser;
}
IdDepartment* CreateDepartment() {
return new SqlserverDepartment;
}
};
//access具体工厂类
class AcessserverFactory :public IFactory {
public:
Iuser* CreateUser() {
return new AccessUser;
}
IdDepartment* CreateDepartment() {
return new AccessDepartment;
}
};
int main() {
User* user = new User;
Department* dept = new Department;
//使用sql,就实例化sql工厂对象
IFactory* factory = new SqlserverFactory;
Iuser* iu = factory->CreateUser();
iu->insert(user);
iu->getUser(1);
IdDepartment* de = factory->CreateDepartment();
de->insert(dept);
de->getUser(2);
return 0;
}
如果增加新的产品,则要修改三处地方,并且增加三个类
策略模式:定义一系列的算法,把他们一个个封装起来,并且使他们可相互替换,具体实现与客户端完全分离,客户端只需要操作一个类就可以实现不同功能
优点:1、减少了算法与使用算法之间的耦合度。 2、测试方便,每个算法都有自己的类,只要测试自己接口就行了,不影响其他算法类。
使用场景: 在分析过程中需要在不同时间应用不同的业务规则,可以考虑用策略模式
#include
#include
using namespace std;
//策略抽象类,定义所有支持的算法的公共接口
class CashSuper {
public:
virtual double acceptCash(double money) {
return money;
}
};
//具体策略类
class NormalFee :CashSuper {
public:
double acceptCash(double money) {
return money;
}
};
class DiscountFee :CashSuper {
public:
float discountNum;
public:
DiscountFee(float discountNum) {
this->discountNum = discountNum;
cout << endl;
}
double acceptCash(double money) {
return money * this->discountNum;
}
};
class ReturnFee :CashSuper {
public:
int fill;
int send;
public:
ReturnFee(int fill, int send) :fill(fill), send(send) {}
double acceptCash(double money) {
if (money > this->fill) {
return money - send;
}
return money;
}
};
//用一个具体策略来配置维护一个对策略对象的引用
class CashContext {
private:
CashSuper* cs = nullptr;
public:
CashContext(int type) {
switch (type) {
case 0:
cs = (CashSuper*) new NormalFee;
break;
case 1:
cs = (CashSuper*)new DiscountFee(0.8);
break;
case 2:
cs = (CashSuper*) new DiscountFee(0.7);
break;
case 3:
cs = (CashSuper*) new DiscountFee(0.5);
break;
case 4:
cs = (CashSuper*) new ReturnFee(300, 100);
break;
}
}
//根据不同策略对象来实现不同结果
double getResult(double money) {
return cs->acceptCash(money);
}
};
int main()
{
const char* discount[5] = { "正常价格","打八折","打七折","打五折" };
//实例化打八折类
CashContext cc(1);
//获取打折后金额
double res = cc.getResult(100);
cout << res << endl;
return 0;
}
策略模式每增加一种功能需要修改工厂类
单例模式:保证一个类仅有一个实例,并提供一个访问他的全局访问点。整个系统只有一个全局对象
#include
using namespace std;
//懒汉式单例模式
class SingletonLazy {
private:
static SingletonLazy* instance;
// 构造函数私有化, 不让外界利用new创建实例
SingletonLazy() {
cout << "懒汉式单例模式\n";
}
public:
static SingletonLazy* getInstance() {
//第一次引用时才被实例化
if (instance == nullptr) {
instance = new SingletonLazy;
}
return instance;
}
};
SingletonLazy* SingletonLazy::instance = nullptr;
//饿汉式单例模式
class SingletonHungry {
private:
static SingletonHungry* instance2;
SingletonHungry() {
cout << "饿汉式单例模式\n";
}
public:
static SingletonHungry* getInstance() {
return instance2;
}
};
//加载时实例化
SingletonHungry* SingletonHungry::instance2 = new SingletonHungry;
int main() {
cout << "action: \n";
return 0;
}
饿汉式单例模式不存在多线程访问的安全问题,但是类一加载就实例化对象,所以要提前占用系统资源。
动态地给一个类添加一些额外的功能。就增加功能来说,装饰器模式相比生成子类更加灵活
#include
#include
using namespace std;
//抽象接口,可以给这些对象动态添加功能
class AbstractPerson {
public:
string username;
string heroname;
int mHp;
int mMp;
int mAt;
int mDf;
public:
virtual void show() = 0;
};
//具体对象
class Person :public AbstractPerson {
public:
Person(string username,string heroname) {
this->username = username;
this->heroname = heroname;
mHp = 0;
mMp = 0;
mAt = 0;
mDf = 0;
}
virtual void show() {
cout << "用户名:" << username << endl;
cout << "英雄名:" << heroname << endl;
cout << "血量:" << mHp << endl;
cout << "魔法:" << mMp << endl;
cout << "攻击:" << mAt << endl;
cout << "防御:" << mDf << endl;
}
};
//装饰类,通过继承方式来实现添加额外功能
class Bazhechongzhuang : public AbstractPerson {
public:
AbstractPerson* per;
public:
Bazhechongzhuang(AbstractPerson* per) :per(per){}
void Add() {
cout << "买了霸者重装后:" << endl;
this->mHp = this->per->mHp;
this->mMp = this->per->mMp;
this->mAt = this->per->mAt;
this->mDf = this->per->mDf + 800;
}
virtual void show() {
Add();
cout << "用户名:" << username << endl;
cout << "英雄名:" << heroname << endl;
cout << "血量:" << this->mHp << endl;
cout << "魔法:" << this->mMp << endl;
cout << "攻击:" << this->mAt << endl;
cout << "防御:" << this->mDf << endl;
}
};
//装饰类
class Fanjia : public AbstractPerson {
public:
AbstractPerson* per;
public:
Fanjia(AbstractPerson* per) :per(per) {}
void Add() {
cout << "买了反甲后:" << endl;
this->mHp = this->per->mHp;
this->mMp = this->per->mMp;
this->mAt = this->per->mAt + 300;
this->mDf = this->per->mDf + 500;
}
virtual void show() {
Add();
cout << "血量:" << this->mHp << endl;
cout << "魔法:" << this->mMp << endl;
cout << "攻击:" << this->mAt << endl;
cout << "防御:" << this->mDf << endl;
}
};
int main() {
AbstractPerson* per = new Person("Timel","典韦");
per->show();
cout << "-------------没买装备------------\n";
Bazhechongzhuang bzcz(per);
Fanjia fj(per);
fj.show();
return 0;
}
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化
#include
using namespace std;
//具体的执行请求
class Request {
public:
void Get() {
cout << "Get!\n";
}
void Post() {
cout << "Post!\n";
}
};
//用来声明执行操作的抽象接口
class Command {
protected:
Request request;
public:
Command() {}
Command(Request& res) :request(res) {}
virtual void excuteCommand() {};//执行
};
//具体执行动作
class GetCommand :public Command {
public:
GetCommand(Request res) :Command(res) {}
void excuteCommand() {
request.Get();
}
};
class PostCommand :public Command {
public:
PostCommand(Request res) :Command(res) {}
void excuteCommand() {
request.Post();
}
};
//具体实施哪个执行动作
class Excutor {
private:
Command* comm;
public:
void setOrder(Command* comm) {
this->comm = comm;
}
void modify() {
comm->excuteCommand();
}
};
int main() {
Request boy;
Command *get = new GetCommand(boy);
Command *post = new PostCommand(boy);
Excutor girl;
girl.setOrder(get);
girl.modify();
girl.setOrder(post);
girl.modify();
return 0;
}
为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一系统更加容易使用。
#include
using namespace std;
class Stock1 {//实现子系统的功能
public:
void buy() {
cout << "买入股票1\n";
}
void sell() {
cout << "卖出股票1\n";
}
};
class Stock2 {
public:
void buy() {
cout << "买入股票2\n";
}
void sell() {
cout << "卖出股票2\n";
}
};
class Stock3 {
public:
void buy() {
cout << "买入股票3\n";
}
void sell() {
cout << "卖出股票3\n";
}
};
//知道哪些子系统类负责处理请求,将客户的请求代理适当的子系统对象
class Fund {
private:
Stock1* sk1;
Stock2* sk2;
Stock3* sk3;
public:
Fund() {
sk1 = new Stock1;
sk2 = new Stock2;
sk3 = new Stock3;
}
void buyFund() {
sk1->buy();
sk2->buy();
sk3->buy();
}
void sellFund() {
sk1->sell();
sk2->sell();
sk3->sell();
}
};
int main() {
Fund f;
f.buyFund();
f.sellFund();
return 0;
}
为其他对象提供一种代理以控制对这个对象的访问。
#include
using namespace std;
class SchoolGirl {
public:
string name;
public:
SchoolGirl() {}
SchoolGirl(const char* name) :name(name) {}
};
//真实对象和代理的共用接口
class AbstractPeople {
public:
virtual void giveDolls() = 0;
virtual void giveFlowers() = 0;
virtual void giveChocolate() = 0;
};
//真实对象
class Pursuit:AbstractPeople {
private:
SchoolGirl *mm;
public:
Pursuit() {}
Pursuit(SchoolGirl* sg) :mm(sg) {}
void giveDolls() {
cout << mm->name << "送你布娃娃" << endl;
}
void giveFlowers() {
cout << mm->name << "送你鲜花" << endl;
}
void giveChocolate() {
cout << mm->name << "送你巧克力" << endl;
}
};
//代理人
class Proxy :AbstractPeople {
private:
Pursuit* ps;
public:
Proxy(SchoolGirl* sg) {
ps = new Pursuit(sg);
}
void giveDolls() {
ps->giveDolls();
}
void giveFlowers() {
ps->giveFlowers();
}
void giveChocolate() {
ps->giveChocolate();
}
};
int main() {
SchoolGirl* sg = new SchoolGirl("娇娇");
Proxy ps(sg);
ps.giveDolls();
ps.giveFlowers();
ps.giveChocolate();
return 0;
}