设计模式(一)之七大原则
单一职责原则
一个类只负责一个职责
如果逻辑简单可以在方法这一级别上保持单一职责
案例 :设计一种交通工具run方法
-
第一种 所有交通工具设计成一个类
class Single_Rseponsibilty1 { public: Single_Rseponsibilty1(); void run(QString str){ qDebug()<< str << "在公路上跑"<<endl; } };
主函数调用
Single_Rseponsibilty1 single_rseponsibilty1; single_rseponsibilty1.run("汽车"); single_rseponsibilty1.run("货车"); single_rseponsibilty1.run("飞机");
输出结果:明显可以看出飞机在公路上跑是错误的描述方式
-
第二种方式 每一种交通工具设计成一个类
class AIR_Single_Rseponsibilty2 { public: AIR_Single_Rseponsibilty2(){} void run(QString str){ qDebug()<< str << "在天空中飞"<<endl; } }; class ROAD_Single_Rseponsibilty2 { public: ROAD_Single_Rseponsibilty2(){} void run(QString str){ qDebug()<< str << "在陆地上跑"<<endl; } }; class WATER_Single_Rseponsibilty2 { public: WATER_Single_Rseponsibilty2(){} void run(QString str){ qDebug()<< str << "在水里上跑"<<endl; } };
主函数调用
AIR_Single_Rseponsibilty2 air; ROAD_Single_Rseponsibilty2 road; WATER_Single_Rseponsibilty2 water; air.run("飞机"); road.run("汽车"); water.run("轮船");
输出结果
-
第三种方式:每种交通工具设计成一个方法
class Single_Rseponsibilty3 { public: Single_Rseponsibilty3(){} void run_water(QString str){ qDebug()<< str << "在水里上跑"<<endl; } void run_air(QString str){ qDebug()<< str << "在天空中飞"<<endl; } void run_road(QString str){ qDebug()<< str << "在陆地上跑"<<endl; } };
主函数调用
Single_Rseponsibilty3 single_rseponsibilty3; single_rseponsibilty3.run_air("飞机"); single_rseponsibilty3.run_road("汽车"); single_rseponsibilty3.run_water("轮船");
输出结果:
小结:每一个类负责单一的职责,在一些逻辑简单的场合可以使用方法级别上的单一职责的原则。
接口隔离原则
一个类对另外一个类的依赖要降到最小。
实现上面的类图
class InterFace1
{
public:
virtual void opreation1(void) = 0;
virtual void opreation2(void) = 0;
virtual void opreation3(void) = 0;
virtual void opreation4(void) = 0;
virtual void opreation5(void) = 0;
//virtual ~InterFace1() = 0;
};
class B1:public InterFace1
{
public:
void opreation1(void) {
qDebug()<<"B1 实现了 op1"<<endl;
}
void opreation2(void) {
qDebug()<<"B1 实现了 op2"<<endl;
}
void opreation3(void) {
qDebug()<<"B1 实现了 op3"<<endl;
}
void opreation4(void) {
qDebug()<<"B1 实现了 op4"<<endl;
}
void opreation5(void) {
qDebug()<<"B1 实现了 op5"<<endl;
}
};
class D1:public InterFace1
{
public:
void opreation1(void) {
qDebug()<<"D1 实现了 op1"<<endl;
}
void opreation2(void) {
qDebug()<<"D1 实现了 op2"<<endl;
}
void opreation3(void) {
qDebug()<<"D1 实现了 op3"<<endl;
}
void opreation4(void) {
qDebug()<<"D1 实现了 op4"<<endl;
}
void opreation5(void) {
qDebug()<<"D1 实现了 op5"<<endl;
}
};
class A1
{
public:
void depend1(InterFace1* dep) {
dep->opreation1();
}
void depend2(InterFace1* dep) {
dep->opreation2();
}
void depend3(InterFace1* dep) {
dep->opreation3();
}
void depend4(InterFace1* dep) {
dep->opreation4();
}
void depend5(InterFace1* dep) {
dep->opreation5();
}
};
class C1
{
public:
void depend1(InterFace1* dep) {
dep->opreation1();
}
void depend2(InterFace1* dep) {
dep->opreation2();
}
void depend3(InterFace1* dep) {
dep->opreation3();
}
void depend4(InterFace1* dep) {
dep->opreation4();
}
void depend5(InterFace1* dep) {
dep->opreation5();
}
};
测试程序
void test_interface(void){
A1* a1 = new A1;
B1* b1 = new B1;
C1* c1 = new C1;
D1* d1 = new D1;
a1->depend1(d1);
c1->depend5(d1);
}
测试结果:这里是通过接口实现两个类之间的通信
依赖倒转原则
核心思想:程序依赖于抽象接口。面向接口编程
接口传递的三种方式
1.通过接口传递实现依赖
//第一种方式通过传递接口实现依赖
class InterfaceTV
{
public:
virtual void play(void) = 0;
};
class InterfaceOpenClose
{
public:
virtual void open(InterfaceTV* itv) = 0;
};
class ChangHong:public InterfaceTV
{
public:
void play(void){
qDebug()<< "播放长虹电视"<<endl;
}
};
class Controller :public InterfaceOpenClose
{
public:
void open(InterfaceTV* itv) {
itv->play();
}
};
2.通过构造函数实现依赖
//第二种方式 通过构造函数来实现
class Interface2TV
{
public:
virtual void play(void) = 0;
};
class Interface2OpenClose
{
public:
virtual void open(void) = 0;
};
class ChangHong2:public Interface2TV
{
public:
void play(void){
qDebug()<< "播放长虹2电视"<<endl;
}
};
class Controller2 :public Interface2OpenClose
{
public:
Controller2(Interface2TV* itv){
mTv = itv;
}
void open(void) {
mTv->play();
}
private:
Interface2TV* mTv;
};
3.通过set方法来实现依赖
//第三种方式 通过set函数
class Interface3TV
{
public:
virtual void play(void) = 0;
};
class Interface3OpenClose
{
public:
virtual void open(void) = 0;
virtual void setTv(Interface3TV* itv) = 0;
};
class ChangHong3:public Interface3TV
{
public:
void play(void){
qDebug()<< "播放长虹3电视"<<endl;
}
};
class Controller3 :public Interface3OpenClose
{
public:
void setTv(Interface3TV* itv){
mTv = itv;
}
void open(void) {
mTv->play();
}
private:
Interface3TV* mTv;
};
输出结果:
里氏替换原则
-
继承包含这样一层含义:父类中已经实现好的方法,不强制要求子类必须遵守这样的契约,但是如果子类对这些已经实现的方法进行任意修改,那么就会对整个继承体系造成破坏。
-
继承给程序带来便利也带来弊端
使用继承的时候尽量不要重写父类的方法。可以通过聚合,组合,依赖来解决问题。
案例 :看一下下面这个案例中重写父类的方法就导致了错误
class A {
public :
int sub (int a , int b){
return a-b;
}
};
//B 类继承自A类
//增加了新功能两个数求差之后再和9相加
class B:public A {
public :
//这里重写了A类的func1方法 可能是无意的
int sub(int a , int b){
return a+b;
}
int func2(int a , int b){
return (func1(a,b)+9);
}
};
这里我们可以抽象出一个更加基础的类来实现两个类都需要的方法或者成员
这里我们抽象出一个Base类 AB都继承自Base
B类想要使用A类的方法那就可以使用组合的方式(聚合,依赖)
class Base {
};
class A : public Base{
public :
int sub (int a , int b){
return a-b;
}
};
//B 类继承自A类
//增加了新功能两个数求差之后再和9相加
class B:public Base {
public :
//这里重写了A类的func1方法 可能是无意的
int sub(int a , int b){
return a+b;
}
int func2(int a , int b){
return (func1(a,b)+9);
}
int func3(int a , int b){
return (ma.sub(a,b)+9);
}
private:
A* ma = new A;
};
开闭原则
模块和函数应该对扩展开放,对修改关闭。扩展开放指的是对提供方来说的,对修改关闭指的是对使用方来说的。
也就是提供方可以扩展,使用方不可以修改。
下面这个类图就是不符合开闭原则的
可以让基类Shape拥有一个Draw方法,而不是GraphicEditor拥有这么多方法。
迪米特法则
-
对自己依赖的类知道打越少越好
-
只与直接朋友通信
直接朋友:每个对象都和其他对象之间有耦合关系。只要有耦合关系这两个对象就是朋友关系。耦合方式有很多 依赖 组合 关联…。如果出现在成员变量,方法参数,方法返回值的对象就是直接朋友。而出现在方法的局部变量的形式就不是直接朋友,要避免这种情况的出现。
Class A{
void func ();
}
Class B{
A ma;//直接朋友
A func1();//直接朋友
void func2(A a);//直接朋友
void func3(){
A tempA;//不是直接朋友 需要避免
}
}
合成复用原则
尽量使用合成 聚合的方式 ,而不使用继承的方式
本文地址:https://blog.csdn.net/qq_14843999/article/details/107374893