迪米特原则,也称为最少知识原则。如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
即一个对象应该对其他对象有最少的了解,就是一个类应该对自己需要耦合或调用的类知道的最少,被耦合或调用的类内部是如何的复杂和我没有任何的关系,我只需知道它们提供的public方法即可。
迪米特法则首先强调的前提是在类的结构设计上,每一个类都应当尽量降低成员的访问权限,也就是说,一个类包装好自己的private状态,不需要让别的类知道的字段或行为就不要公开。
面向对象的设计原则和面向对象的三大特性本就不是矛盾的,迪米特法则根本思想,是强调了类之间的松耦合。
我们在程序设计时,类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及,也就是说,信息的隐藏促进了软件的复用。
设想这样一个案例,假如要买房,目前有A、B两套房,分别是高品质和低品质,购房者直接和这两套房打交道,购买符合自己意愿的房。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
//抽象的基类
class AbstractBuilding
{
public:
virtual void sale() = 0; //售卖函数
virtual string getQuality() = 0; //获取质量
};
//楼盘A 高品质
class BuildingA :public AbstractBuilding
{
public:
//构造函数
BuildingA()
{
this->mQulity = "高品质";
}
//重写sale函数
virtual void sale()
{
cout << "楼盘A " << mQulity << " 被售卖" << endl;
}
//重写getQuality函数
virtual string getQuality()
{
return this->mQulity;
}
public:
string mQulity;
};
//楼盘B 低品质
class BuildingB :public AbstractBuilding
{
public:
//构造函数
BuildingB()
{
this->mQulity = "低品质";
}
//重写sale函数
virtual void sale()
{
cout << "楼盘B " << mQulity << " 被售卖" << endl;
}
//重写getQuality函数
virtual string getQuality()
{
return this->mQulity;
}
public:
string mQulity;
};
//还可以动态增加楼盘
//客户端调用
void test01()
{
BuildingA* ba = new BuildingA;
//如果是低品质就买了
if (ba->mQulity == "低品质")
{
ba->sale();
}
BuildingB* bb = new BuildingB;
//如果是低品质就买了
if (bb->mQulity == "低品质")
{
bb->sale();
}
}
int main(int argc, int* argv[])
{
test01();
system("pause");
return 0;
}
这就是客户端直接和这两套房打交道。但是其实没必要的,如果”房源“一直扩充,客户端也得跟着添加对应的房源, 而且客户端没必要知道房的具体信息。
使用迪米特原则来处理这个问题,也就是客户可以直接找“中介”,告诉“中介”自己需要什么类型的房,”中介“去和具体的房打交道,这就减少了客户端和房源的具体交接。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
//迪米特法则 又叫 最少知识法则
//暴露接口即可,知道越少,能把事办好
//抽象的基类
class AbstractBuilding
{
public:
virtual void sale() = 0; //售卖函数
virtual string getQuality() = 0; //获取质量
};
//楼盘A 高品质
class BuildingA :public AbstractBuilding
{
public:
//构造函数
BuildingA()
{
this->mQulity = "高品质";
}
//重写sale函数
virtual void sale()
{
cout << "楼盘A " << mQulity << " 被售卖" << endl;
}
//重写getQuality函数
virtual string getQuality()
{
return this->mQulity;
}
public:
string mQulity;
};
//楼盘B 低品质
class BuildingB :public AbstractBuilding
{
public:
//构造函数
BuildingB()
{
this->mQulity = "低品质";
}
//重写sale函数
virtual void sale()
{
cout << "楼盘B " << mQulity << " 被售卖" << endl;
}
//重写getQuality函数
virtual string getQuality()
{
return this->mQulity;
}
public:
string mQulity;
};
//增加中介类 直接和它打交道 凡是动态扩展的就抽象出来
//需要这个类去维护这些对象
class Mediator
{
public:
//构造函数
Mediator()
{
//创建好已有的楼盘,加进来
AbstractBuilding* building = new BuildingA;
vBuilding.push_back(building); //加入楼盘A
building = new BuildingB;
vBuilding.push_back(building); //加入楼盘B
}
//析构函数
~Mediator()
{
for (vector<AbstractBuilding*>::iterator it = vBuilding.begin(); it != vBuilding.end(); it++)
{
if (*it != NULL)
{
delete *it; //释放
}
}
}
//对外暴露接口
AbstractBuilding* findMyBuiding(string quality)
{
//遍历
for (vector<AbstractBuilding*>::iterator it = vBuilding.begin(); it != vBuilding.end(); it++)
{
//找到返回
if ((*it)->getQuality() == quality)
{
return (*it);
}
}
return NULL;
}
public:
vector<AbstractBuilding*> vBuilding; //用来管理楼盘类,因为不是某个具体,所以用抽象类
};
//客户端
void test02()
{
Mediator* media = new Mediator;
AbstractBuilding* building = media->findMyBuiding("高品质");
//找到就卖出
if (building != NULL)
{
building->sale();
}
else
{
cout << "没有符合您条件的楼盘" << endl;
}
}
int main(int argc, int* argv[])
{
test02();
system("pause");
return 0;
}