系列文章目录
前言
为什么我们要在软件开发中使用设计模式。
-
为了代码可重用性、增加可维护性,让代码更容易被他人理解、保证代码可靠性。设计模式使代码编写真正工程化。
-
设计模式已经经历了很长一段时间的发展,它们提供了软件开发过程中面临的一般问题的最佳解决方案。学习这些模式有助于经验不足的开发人员通过一种简单快捷的方式来学习软件设计。
-
能够使我们的代码更加结构化,清晰明了
|版本声明:山河君,未经博主允许,禁止转载
一、迪米特法则定义
乍一看“迪米特法则”这个名字听起来不太符合一个程序员的命名,但这一法则却不仅仅局限于计算机领域,在其他领域也同样适用。比如,美国人就在航天系统的设计中采用这一法则。
百度词条上定义:迪米特法则(Law of Demeter)又叫作最少知识原则(The Least Knowledge Principle),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。英文简写为: LOD。
什么叫做朋友呢?
其实朋友类意思就是为耦合类,这里的朋友定义:
1.类成员变量
2.某个类成员函数参数为类对象
3.某个类成员函数返回值为类对象
而方法体内部的类不属于朋友类。
在编程上,它变成具有以下特点:
1.如果两个类不直接通信,那么这两个类就不应该发生直接的相互作用。
2.在类的结构设计上,每一个类都应该尽量降低成员的访问权限
3.该法则在适配器模式、解释模式等中有强烈的体现
4.强调类之间的松耦合,类之间的耦合越弱,越有利于复用
二、使用场景
我们现在在做一个实际音频的控制,它具有以下功能:
1.可以打开耳机
2.可以关闭耳机
3.可以打开麦克风
4.可以关闭麦克风
5.麦克风可以选择声卡样式
6.电脑开机时初始化打开耳机,耳机初始化同时初始化打开麦克风和选择默认声卡
你可能直接一个类搞定,有如下设计:
class VideoEngine
{
public:
//麦克风
void openMicrophone() {};
void closeMicrophone() {};
public:
//声音
void openVoice() {};
void closeVoice() {};
public:
//声卡样式
void soundCardType1();
void soundCardType2();
void soundCardType3();
};
int main(int argv, char* argc[])
{
VideoEngine videoEngine;
videoEngine.openVoice();
videoEngine.openMicrophone();
videoEngine.soundCardType1();
return 0;
}
但是它实际上违反了单一职责原则,VideoEngine存在三个功能(麦克风、声音、选择声卡)
那你可能又觉得把这三个功能进行分开就好了,我们来分析一下功能:
1.因为麦克风可以选择声卡样式,所以麦克风类Microphone类和声卡类soundCard是耦合的
2.电脑开机时先检测有没有耳机的(一般没有耳机怎么会有麦克风呢,别杠~),而耳机初始化同时要初始化麦克风,所以在voice调用init同时要 init麦克风,这两个类也是有一定耦合的
有如下设计:
class Voice
{
public:
void Init(Microphone* pmircrophone)
{
openVoice();
soundCard* psoundCard = pmircrophone->m_soundCard;
psoundCard->soundCardType1();
}
//声音
void openVoice() {};
void closeVoice() {};
};
class soundCard
{
public:
void soundCardType1() {};
void soundCardType2() {};
void soundCardType3() {};
};
class Microphone
{
public:
void Init()
{
openMicrophone();
m_soundCard = new soundCard;
}
//麦克风
void openMicrophone() {};
void closeMicrophone() {};
public:
soundCard* m_soundCard;
};
int main(int argv, char* argc[])
{
Microphone* pMicrophone = new Microphone;
Voice voice;
voice.Init(pMicrophone);
return 0;
}
这就违反了迪米特法则——如果两个类不直接通信,那么这两个类就不应该发生直接的相互作用。上面我们分析了Voice和Microphone是耦合也就是朋友,Microphone和soundCard也是朋友,但是soundCard和Voice不是朋友。
而Voice的init方法中soundCard* psoundCard = pmircrophone->m_soundCard;
突然出现了Voice根本不知道的类soundCard,voice类只知道成员函数和成员变量,在方法内部出现了它不知道的东西无疑是很糟糕的,所以要进行避免。
这样Init的时候直接设置soundCard就行了。
class Microphone
{
public:
void Init()
{
openMicrophone();
m_soundCard = new soundCard;
openType1();
}
void openType1() { m_soundCard->soundCardType1() };
void openType2() { m_soundCard->soundCardType2() };
void openType3() { m_soundCard->soundCardType3() };
//麦克风
void openMicrophone() {};
void closeMicrophone() {};
public:
soundCard* m_soundCard;
};
但是这样就结束了吗?
别忘了原则中 说一个类对其它类了解的越少越好,这也就要求在类的结构设计上,每一个类都应该尽量降低成员的访问权限。而Microphone几乎可以访问soundCard的所有接口,应该如下修改
class soundCard
{
public:
void chooseType(int i)
{
}
private:
void soundCardType1() {};
void soundCardType2() {};
void soundCardType3() {};
};
class Microphone
{
public:
void Init()
{
openMicrophone();
m_soundCard = new soundCard;
m_soundCard->chooseType(1);
}
//麦克风
void openMicrophone() {};
void closeMicrophone() {};
public:
soundCard* m_soundCard;
};
总结
持续更新中!!!
如果对您有所帮助,请点个赞吧!