由Python外观设计模式引入设计原则之——迪米特法则

1.引言

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2. 迪米特法则

迪米特法则又称最少知识原则(least knowledge principle)简称LKP。意思是说一个对象应该对其他对象有尽可能少的了解,不和陌生人说话。

迪米特法则的一个解释是(talk only to your immediate friends)。只与直接朋友对话。什么是直接朋友呢。两个类有耦合就是朋友关系。直接朋友,我的理解是类之间是通过参数调用产生关系的,而不是直接内嵌的。

2.1.模式与意义

2.1.1 摘自百度百科

迪米特法则可以简单说成:talk only to your immediate friends。 对于OOD来说,又被解释为下面几种方式:一个软件实体应当尽可能少的与其他实体发生相互作用。每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。

迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。

迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系——这在一定程度上增加了系统的复杂度。

有兴趣可以研究一下设计模式的门面模式(Facade)和中介模式(Mediator),都是迪米特法则应用的例子。

2.1.2 摘自大话设计模式

迪米特法则,如果两个类不必彼此直接通向,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个累哦的某一个方法的话,可以通过第三者转发这个调用。

迪米特法则首先强调的前提是在类的结构设计上,每一个类都应当降低成员的访问权限,也就是说,一个类包装好自己的private状态,不需要让别的类知道的字段或行为就不要公开。

面向对象的设计原则和面向对象的三大特性本就不是矛盾的。迪米特法则其根本思想,是强调了类之间的松耦合。类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成搏击,也就是说,信息的隐藏促进了软件的复用。

3.示例

3.1 不遵从迪米特原则的例子

体育课上,体育老师要进行点名,她让体育课代表去点名。类Teacher与类 StudentList, Student, Representative都有耦合关系,但他们都是内嵌到类Teacher的command方法中。
这就不符合迪米特原则了。代码如下

class Teacher(object):
 
    def __init__(self):
        pass
 
    def command(self):
        print('体育老师让课代表点名')
        studentlist = StudentList()
        for _ in range(20):
            studentlist.append(Student())
        print('课代表开始点名')
        representative = Representative()
        representative.count(studentlist)
 
 
class Student(object):
    pass
 
 
class StudentList(list):
    pass
 
 
class Representative(object):
 
    def count(self, studentlist):
        print('课代表已经点完名,共有人数%d' % len(studentlist))
 
 
class Client(object):
 
    def main(self, teacher):
        teacher.command()
 
if __name__ == '__main__':
    client = Client()
    teacher = Teacher()
    client.main(teacher)

结果如下

体育老师让课代表点名
课代表开始点名
课代表已经点完名,共有人数20

3.2 把上面的代码修改为符合迪米特原则

从上面的代码可知,teacher的下级是representative,其应该只与representative是直接朋友关系。representative也应该只与studentlist是直接朋友关系。因此代码可以修改为这样:

class Teacher(object):
 
    def __init__(self, representative):
        self.representative = representative
 
    def command(self):
        print('老师让课代表点名')
        self.representative.count()
 
 
class Representative(object):
 
    def __init__(self, studentlist):
        self.studentlist = studentlist
 
    def count(self):
        print('课代表开始点名')
        self.studentlist.size()
 
 
class StudentList(list):
 
    def add_student(self, num):
        for _ in range(num):
            self.append(Student())
 
    def size(self):
        print('学生的人数为%s' % str(len(self)))
 
 
class Student(object):
    pass
 
 
class Client(object):
    def main(self, teacher):
        teacher.command()
 
if __name__ == '__main__':
    studentlist = StudentList()
    studentlist.add_student(10)
    representative = Representative(studentlist)
    teacher = Teacher(representative)
    client = Client()
    client.main(teacher)

结果如下

老师让课代表点名
课代表开始点名
学生的人数为10

从修改后的代码可以看出,teacher,representative,studentlist是层级关系,这种关系也可以以内嵌的形式都写进teacher的command方法中,也可以像修改后的代码一样,采用逐级传递参数的方式来反映层级关系。

发布了146 篇原创文章 · 获赞 66 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_38923792/article/details/102515968
今日推荐