设计模式6原则之:迪米特法则
概念
迪米特法则:又叫【最少知道原则】,一个类不应该知道自己操作的类的细节,也就是说,只和朋友谈话,不和陌生人谈话
理解
-
一个类不应该知道自己操作的类的细节
有这样一个场景,我们课件中有一个视频小节,现在需要更新它。更新它需要 3 个步骤:验证参数合法性,参数转化,保存到数据库
我们可以写成下面这样:
class Courseware { public function updateVideoChapter(VideoChapter chapter) { chaper->checkParam(); chaper->transferParam(); chaper->save(); } } class VideoChapter { public function checkParam() { echo '校验参数'; } public function transferParam() { echo '转换参数'; } public function save() { echo '保存小节'; } }
这种情况,很明显的违反了迪米特法则,因为课件保存小节不需要知道小节保存的具体步骤,增加了代码的耦合度
正确的做法是封装一层,只需要提供一个小节保存的方法就行,也就是隐藏操作的类的细节
class Courseware { public function updateChapter(IChapter chapter) { chaper->update(); } } interface Ichapter { function update(); } class VideoChapter implements IChapter { public function update() { this->checkParam(); this->transferParam(); this->save(); echo '更新视频'; } public function checkParam() { echo '校验参数'; } public function transferParam() { echo '转换参数'; } public function save() { echo '保存小节'; } }
-
只和朋友谈话,不和朋友的朋友谈话
继续上面的更新小节的例子,假如现在需要对更新小节增加日志功能,记录谁更新了哪些字段,因此我们需要引入记录日志的方法
class Courseware { public function updateChapter(IChapter chapter) { chaper->update(); // 记录日志 (new Logger())->insert(); } } interface Ichapter { function update(); } class VideoChapter implements IChapter { public function update() { this->checkParam(); this->transferParam(); this->save(); echo '更新视频'; } public function checkParam() { echo '校验参数'; } public function transferParam() { echo '转换参数'; } public function save() { echo '保存小节'; } }
你以为这样就没事了,但是还是违反了迪米特法则。
咱们可以看下什么是课件类
Courseware
的朋友,(出现在成员变量、方法的输入输出参数中的类就是朋友),所以小节类就是课件类的朋友,日志类就不是课件类的朋友。这时候就需要修改成下面这样:
class Courseware { public function updateChapter(IChapter chapter) { chaper->update(); } } interface Ichapter { function update(); } class VideoChapter implements IChapter { public Logger logger; public function __construct() { this->logger = new Logger(); } public function update() { this->checkParam(); this->transferParam(); this->save(); // 记录日志 this->logger->insert(); echo '更新视频'; } public function checkParam() { echo '校验参数'; } public function transferParam() { echo '转换参数'; } public function save() { echo '保存小节'; } }
这样课件类和小节类就可以继续做好朋友了。