面向对象设计原则表
名称 | 定义 |
---|---|
单一职责原则(Single Responsibility Principle, SRP)★★★★☆ | 类的职责单一,对外只提供一种功能,而引起类变化的原因都应该只有一个。 |
开闭原则(Open-Closed Principle, OCP)★★★★★ | 类的改动是通过增加代码进行的,而不是修改源代码。 |
里氏代换原则(Liskov Substitution Principle, LSP)★★★★★ | 任何抽象类出现的地方都可以用他的实现类进行替换,实际就是虚拟机制,语言级别实现面向对象功能。 |
依赖倒转原则(Dependence Inversion Principle, DIP)★★★★★ | 依赖于抽象(接口),不要依赖具体的实现(类),也就是针对接口编程。 |
接口隔离原则(Interface Segregation Principle, ISP)★★☆☆☆ | 不应该强迫用户的程序依赖他们不需要的接口方法。一个接口应该只提供一种对外功能,不应该把所有操作都封装到一个接口中去。 |
合成复用原则(Composite Reuse Principle, CRP)★★★★☆ | 如果使用继承,会导致父类的任何变换都可能影响到子类的行为。如果使用对象组合,就降低了这种依赖关系。对于继承和组合,优先使用组合。 |
迪米特法则(Law of Demeter, LoD)★★★☆☆ | 一个对象应当对其他对象尽可能少的了解,从而降低各个对象之间的耦合,提高系统的可维护性。例如在一个程序中,各个模块之间相互调用时,通常会提供一个统一的接口来实现。这样其他模块不需要了解另外一个模块的内部实现细节,这样当一个模块内部的实现发生改变时,不会影响其他模块的使用。(黑盒原理) |
开闭原则案例
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//计算器类
class Caculaor
{
public:
Caculaor(int a, int b, string moperator)
{
this->m_a = a;
this->m_b = b;
this->m_operator = moperator;
}
int getResult()
{
if (m_operator.compare("+") == 0)
{
return m_a + m_b;
}
else if (m_operator.compare("-") == 0)
{
return m_a - m_b;
}
else if (m_operator.compare("*") == 0)
{
return m_a * m_b;
}
else if (m_operator.compare("/") == 0)
{
return m_a / m_b;
}
}
private:
int m_a;
int m_b;
string m_operator;
int m_ret;
};
/*
缺点: 如果增加取模的运算 需要修改getResult成员方法,如果增加新功能的情况下要修改源代码,那么
就会有修改出错的可能性。我们应该在增加新的功能时候,不能影响其他已经完成的功能。这就是对修改关闭,
对扩展开放,叫做开闭原则
*/
void test01()
{
Caculaor* caculator = new Caculaor(10, 20, "+");
cout << caculator->getResult() << endl;
}
/* 计算器 开闭原则 start */
//计算器的抽象类
class AbstractCaculator
{
public:
AbstractCaculator(int a, int b) :m_a(a), m_b(b) {}
virtual int getResult() = 0;
protected:
int m_a;
int m_b;
};
//加法类
class Plus : public AbstractCaculator
{
public:
Plus(int a, int b) :AbstractCaculator(a, b) {}
virtual int getResult() {
return m_a + m_b;
}
};
//减法类
class Minute : public AbstractCaculator
{
public:
Minute(int a, int b) :AbstractCaculator(a, b) {}
virtual int getResult() {
return m_a - m_b;
}
};
void test02()
{
AbstractCaculator* caculator = NULL;
caculator = new Plus(10, 20);
cout << caculator->getResult() << endl;
delete caculator;
caculator = new Minute(10, 20);
cout << caculator->getResult() << endl;
}
/* 计算器 开闭原则 end */
int main()
{
//test01();
test02();
system("pause");
return EXIT_SUCCESS;
}
迪米特法则案例
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<list>
using namespace std;
//楼盘基类
class AbstractBuilding
{
public:
AbstractBuilding(string quality) :m_quality(quality) {}
virtual void sale() = 0;
string getQuality()
{
return m_quality;
}
protected:
string m_quality; //楼盘品质
};
//A楼盘
class BuildingA : public AbstractBuilding
{
public:
BuildingA(string quality) :AbstractBuilding(quality) {}
virtual void sale()
{
cout << "A楼盘售卖" << m_quality << "的房子" << endl;
}
};
//B楼盘
class BuildingB : public AbstractBuilding
{
public:
BuildingB(string quality) :AbstractBuilding(quality) {}
virtual void sale()
{
cout << "B楼盘售卖" << m_quality << "的房子" << endl;
}
};
//房屋中介
class BuildingMediator
{
public:
BuildingMediator()
{
AbstractBuilding* building = NULL;
building = new BuildingA("低档品质");
this->addNewBuilding(building);
building = new BuildingB("高档品质");
this->addNewBuilding(building);
}
void addNewBuilding(AbstractBuilding* building)
{
m_list.push_back(building);
}
AbstractBuilding* findBuilding(string quality)
{
for (list<AbstractBuilding*>::iterator it = m_list.begin(); it != m_list.end(); it++)
{
if ((*it)->getQuality().compare(quality) == 0)
{
return *it;
}
}
return NULL;
}
private:
list<AbstractBuilding*> m_list;
};
void test01()
{
BuildingMediator* mediator = new BuildingMediator;
AbstractBuilding* building = mediator->findBuilding("高档品质");
if (building != NULL)
{
building->sale();
}
else
{
cout << "没有符合要求的楼盘!" << endl;
}
}
int main() {
test01();
system("pause");
return EXIT_SUCCESS;
}
合成复用原则案例
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Car
{
public:
virtual void run() = 0;
};
class BWMCar : public Car
{
public:
virtual void run()
{
cout << "宝马车启动..." << endl;
}
};
class DazhongCar : public Car
{
public:
virtual void run()
{
cout << "大众车启动..." << endl;
}
};
class PersonA : public BWMCar
{
public:
void drive()
{
run();
}
};
void test01()
{
PersonA* person = new PersonA;
person->drive();
}
/*
合成复用原则
对于继承和组合 优先使用组合
*/
class PersonB
{
public:
PersonB(Car* car)
{
pCar = car;
}
void drive()
{
pCar->run();
}
~PersonB()
{
if (pCar != NULL)
{
delete pCar;
}
}
private:
Car* pCar;
};
void test02()
{
PersonB* person = new PersonB(new BWMCar);
person->drive();
delete person;
person = new PersonB(new DazhongCar);
person->drive();
delete person;
}
int main()
{
//test01();
test02();
system("pause");
return EXIT_SUCCESS;
}
依赖倒转原则案例
传统的设计模式通常是自顶向下逐级依赖,这样,底层模块,中间层模块和高层模块的耦合度极高,若任意修改其中的一个,很容易导致全面积的修改,非常麻烦,那么依赖倒转原则利用多态的先天特性,对中间抽象层进行依赖,这样,底层和高层之间进行了解耦合。
下面我们继续看一个符合依赖倒转原则的例子:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class BankWorker
{
public:
void payService()
{
cout << "办理付款业务" << endl;
}
void transferService()
{
cout << "办理转账业务" << endl;
}
void saveService()
{
cout << "办理存款业务" << endl;
}
};
void test01()
{
BankWorker* worker = new BankWorker;
worker->payService();//存款业务
worker->saveService(); //存款业务
worker->transferService();//转账业务
}
//依赖倒转原则
//抽象层
class AbstractWorkerBank
{
public:
virtual void doBussiness() = 0;
};
//只办理存款业务
class SaveBankWorker : public AbstractWorkerBank
{
public:
virtual void doBussiness()
{
cout << "办理存款业务" << endl;
}
};
//只办理转账业务
class TransferBankWorker : public AbstractWorkerBank
{
public:
virtual void doBussiness()
{
cout << "办理存款业务" << endl;
}
};
//只办理付款业务
class PayBankWorker : public AbstractWorkerBank
{
public:
virtual void doBussiness()
{
cout << "办理存款业务" << endl;
}
};
//高层模块
void DoBankBussiness(AbstractWorkerBank* worker)
{
worker->doBussiness();
delete worker;
}
void test02()
{
DoBankBussiness(new SaveBankWorker); //办理存款业务
DoBankBussiness(new TransferBankWorker); //办理转账业务
DoBankBussiness(new PayBankWorker); //办理付款业务
}
int main()
{
//test01();
test02();
system("pause");
return EXIT_SUCCESS;
}