软件设计模式种类:23个
创建型(Creational)模式:如何创建对象。
结构型(Structural)模式:如何实现类或者对象的组合。
行为型(Behavioral)模式:类或者对象怎样交互以及怎样分配职责。
设计模式的基础:多态
C++中的多态简单的理解为定义一个行为方法,不同的对象进行这个行为时产生不同的状态。分为静态多态(编译时多态性)和动态多态(运行时多态性)两种。
静态多态:通过函数的重载来实现的(运算符重载实际上也属于函数的重载)。编译器在编译期间根据函数实参类型(可能进行隐式类型转移),可推断出要调用那个函数,如果有对应的函数就调用该函数,否则出现编译错误。
动态多态:程序运行过程中才动态地确定操作所针对的对象,运行时多态性是通过虚函数来实现的。在程序期间判断所引用的所引用的实际类型,根据实际类型调用对应的方法。virtual关键字修饰类的成员函数时,指明该函数为虚函数,派生类需要重新实现,编译器将实现动态绑定。(静态成员函数不能是虚函数)
面向对象设计:
单一职责原则(SRP):类的职责单一,对外只提供一种功能。
开闭原则(OCP):类的改动通过增加代码实现
里氏变换原则(LSP):任何抽象类出现的地方都可以用他的实现类进行替换,实现虚拟机制,语言上实现面向对象的功能。
依赖倒转原则(DIP) :依赖于抽象(接口),不依赖具体的实现类,面向接口编程。
接口隔离原则(ISP) :一个接口只提供一种对外功能,不应该把所有操作封装到一个接口中去。
合成复用原则(CRP):对于继承组合,优先使用组合。
迪米特法则(LoP):一个对象应当尽可能减少与其他对象的了解,降低各个对象之间的耦合。
开闭原则(OCP)
示例:
#include<iostream>
using namespace std;
class AbstractCaculator {
public:
virtual int getresult() = 0;
virtual void setOperNumber(int a,int b) = 0;
};
class PlusCaculator : public AbstractCaculator {
public:
virtual void setOperNumber(int a, int b) {
this->m_a = a;
this->m_b = b;
}
virtual int getresult() {
return m_a + m_b;
}
private:
int m_a;
int m_b;
};
class subCaculator : public AbstractCaculator {
public:
virtual void setOperNumber(int a, int b) {
this->m_a = a;
this->m_b = b;
}
virtual int getresult() {
return m_a - m_b;
}
private:
int m_a;
int m_b;
};
class MultiplyCaculator : public AbstractCaculator {
public:
virtual void setOperNumber(int a, int b) {
this->m_a = a;
this->m_b = b;
}
virtual int getresult() {
return m_a * m_b;
}
private:
int m_a;
int m_b;
};
void test01() {
AbstractCaculator* caculator = new PlusCaculator;
caculator->setOperNumber(10, 20);
cout << caculator->getresult() << endl;
}
int main() {
test01();
return 0;
}
迪米特法则:
示例:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
// 迪米特法则
class AbstractBuilding {
public:
virtual void sale() = 0;
virtual string getbuilding() = 0;
};
class BuildingA : public AbstractBuilding {
public:
BuildingA() {
m_Qulity = "high qulity";
}
virtual void sale() {
cout << "high qulity builda is saled" << endl;
}
virtual string getbuilding() {
return m_Qulity;
}
public:
string m_Qulity;
};
class BuildingB : public AbstractBuilding {
public:
BuildingB() {
m_Qulity = "low qulity";
}
virtual void sale() {
cout << "low qulity builda is saled" << endl;
}
virtual string getbuilding() {
return m_Qulity;
}
public:
string m_Qulity;
};
void test01() {
BuildingA* ba = new BuildingA;
if (ba->m_Qulity == "high qulity") {
ba->sale();
}
BuildingB* bb = new BuildingB;
if (bb->m_Qulity == "low qulity") {
bb->sale();
}
}
//中介类
class Modiator {
public:
Modiator() {
AbstractBuilding* building = new BuildingA;
vBuilding.push_back(building);
building = new BuildingB;
vBuilding.push_back(building);
}
AbstractBuilding* findmybuilding(string quality) {
for (vector<AbstractBuilding*>::iterator it = vBuilding.begin(); it != vBuilding.end(); it++) {
if ((*it)->getbuilding() == quality) {
return *it;
}
}
return NULL;
}
~Modiator() {
for (vector<AbstractBuilding*>::iterator it = vBuilding.begin(); it != vBuilding.end(); it++) {
if (*it != NULL) {
delete* it;
}
}
}
public:
vector<AbstractBuilding*> vBuilding;
};
void test02() {
Modiator* med = new Modiator;
AbstractBuilding* building = med->findmybuilding("low qulity");
if (building == NULL) {
cout << "building is saled" << endl;
}
else {
cout << "you can pay for the building" << endl;
}
}
int main() {
//test01();
test02();
return 0;
}
合成复用原则(CRP)
示例:
#include<iostream>
using namespace std;
class AbstractCar {
public:
virtual void run() = 0;
};
class dazhong : public AbstractCar {
public:
virtual void run() {
cout << "dazhong" << endl;
}
};
class tuolaji : public AbstractCar {
public:
virtual void run() {
cout << "tuolaji" << endl;
}
};
#if(0)
class Preson : public tuolaji {
public:
void doufeng() {
run();
}
};
class Preson1 : public dazhong {
public:
void doufeng() {
run();
}
};
#endif
//使用组合
class Preson {
public:
void setCar(AbstractCar* car) {
this->m_car = car;
}
void doufeng() {
this->m_car->run();
if (this->m_car != NULL) {
delete this->m_car;
}
}
public:
AbstractCar* m_car;
};
void test02() {
Preson p;
p.setCar(new dazhong);
p.doufeng();
}
int main() {
test02();
return 0;
}
依赖倒转原则
传统的模块高层次的模块依赖于低层次的模块,抽象层依赖于具体层。
依赖倒转原则将其进行反转。
示例:
#include<iostream>
using namespace std;
class AbstractBankworker {
public:
virtual void doBusiness() = 0;
};
class Saveworker : public AbstractBankworker {
public:
virtual void doBusiness() {
cout << "存款业务" << endl;
}
};
class PayBankworker : public AbstractBankworker {
public:
virtual void doBusiness() {
cout << "转账业务" << endl;
}
};
//中层业务
void doNewBusiness(AbstractBankworker* worker) {
worker->doBusiness();
}
void test02() {
AbstractBankworker* pay = new PayBankworker;
doNewBusiness(pay);
}
int main() {
test02();
return 0;
}
总结:
开闭原则:对修改关闭,对增加代码关闭。
迪米特法则:又叫最少知识原则,降低各个对象之间的耦合,提高系统可维护性。
组合复用原则:尽量使用组合原则。
依赖倒转原则:高层业务逻辑依赖抽象层,实现层依赖抽象层,以此实现可扩展性。