23、Python与设计模式--设计原则

简介: #一、六大设计原则 在法理学中,法律规则与法律原则都是法律规范的重要构成。但二者也会有些不同:法律规则是指采取一定的结构形式具体规定人们的法律权利、法律义务以及相应的法律后果的行为规范,内容比较明确,比如,交通法规中规定,禁止闯红灯;法律原则是指在一定法律体系中作为法律规则的指导思想,基本或本原的、综合的、稳定的原理和准则,内容上只包含“大方针”,而并未有具体规则,比如,如果车上有马上临产的孕妇

一、六大设计原则

在法理学中,法律规则与法律原则都是法律规范的重要构成。但二者也会有些不同:法律规则是指采取一定的结构形式具体规定人们的法律权利、法律义务以及相应的法律后果的行为规范,内容比较明确,比如,交通法规中规定,禁止闯红灯;法律原则是指在一定法律体系中作为法律规则的指导思想,基本或本原的、综合的、稳定的原理和准则,内容上只包含“大方针”,而并未有具体规则,比如,如果车上有马上临产的孕妇,闯红灯不会被处罚,这是符合重视生命的原则。设计模式与设计原则,基本符合规则与原则的关系,设计模式是一个个具体问题的解决方案,设计原则则反映了这些设计模式的指导思想;同时,设计原则可衍生出的设计模式也不仅限于上述介绍到了23种设计模式,任何一种针对特定业务场景中的解决方法,虽然找不到对应的设计模式与之匹配,但若符合设计原则,也可以认为是一种全新的设计模式。从这个意义上来说,设计模式是程序设计方法的形,而设计原则是程序设计方法的神。

1、单一职责原则

单一职责原则英文原名为Single Responsibility Principle,简称SRP原则。其含义为:应该有且仅有一个原因引起类的变更。举个例子来说明单一职责原则:一个视频播放系统,一个客户端类有两个功能接口,即视频播放接口和音频播放接口。虽然这样的设计很常见,但却不满足单一职责原则的。原因是,如果对视频播放有变更需求或者对音频播放有修改需求,都会变更视频客户端的类结构。符合单一原则的设计是,将视频播放单元和音频播放单元各建一个类,播放客户端继承两个类,构成客户端。
单一职责原则的最大难点在于职责的划分,试想,以上划分是否是符合单一职责了?既是,也不是。试想,如果将视频传输和音频传输的协议信息和数据信息区分开,为符合这种粒度的单一职责原则就必须要有协议传输类和数据传输类的划分。如果接着细分,可能一个简单的小模块,都要设计非常多的类。因此,单一职责原则粒度的选择,应该根据业务流程和人员分工来进行考虑。一些基本的划分,似乎已经成了行业规范性的内容,比如,业务逻辑与用户信息管理的划分等。

2、里氏替换原则

里氏替换原则英文原名为Liskov Substitution Principle,简称LSP原则。它是面向对象设计的最为基本原则之一。 里氏替换原则的含义为:任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当子类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,子类也能够在基类的基础上增加新的行为。举例说明:对于一个鸟类,可以衍生出麻雀、喜鹊、布谷等子类,这些子类都可继承鸟类的鸣叫、飞行、吃食等接口。而对于一个鸡类,虽然它在生物学上属于鸟类,但它不会飞,那么符合LSP设计原则的情况下,鸡就不应该是鸟的一个子类:在鸟类调用飞行接口的地方,鸡类并不能出现。如果鸡类要使用鸟类的接口,应该使用关联关系,而不是继承关系。

3、依赖倒置原则

依赖倒置原则英文原名为Dependence Inversion Principle,简称DIP原则。它的含义为:高层模块不应该依赖于低层模块,两者都应该依赖其抽象。抽象不应该依赖于细节,细节应该依赖于抽象。我们将每个不可细分的逻辑叫作原子逻辑,原子逻辑组装,形成低层模块,低层模块组装形成高层模块。依赖倒置原则的含义为,高层模块和低层模块都应该由各自的抽象模块派生而来,同时接口设计应该依赖于抽象,而非具体模块。举个例子:司机与汽车是依赖的关系,司机可以有实习司机类、老司机类等派生;汽车可以有轿车、SUV、卡车等派生类。如果司机中设计一个接口drive,汽车是其参数,符合DIP设计原则的参数,应该是在基类司机类中,将基类汽车类作为参数,而司机的派生类中,drive的参数同样应该为基类汽车类,而不应该是汽车类的任一个派生类。如果规定实习司机只能开轿车等业务逻辑,应该在其接口中进行判断,而不应该将参数替换成子类轿车。

4、接口隔离原则

接口隔离原则英文原名为Interface Segregation Principle,简称ISP原则。其含义为:类间的依赖关系不应该建立一个大的接口,而应该建立其最小的接口,即客户端不应该依赖那些它不需要的接口。这里的接口的概念是非常重要的。从逻辑上来讲,这里的接口可以指一些属性和方法的集合;从业务上来讲,接口就可以指特定业务下的接口(如函数,URL调用等)。接口应该尽量小,同时仅留给客户端必要的接口,弃用没有必要的接口。举例说明:如果要根据具体的数据,生成饼图、直方图、表格,这个类该如何设计?如果将生成饼图、直方图、表格等“接口”(这里的接口就是“操作”的集合的概念),写在一个类中,是不符合接口隔离原则的。符合ISP原则的设计应该是设计三个类,每个类分别实现饼图、直方图、表格的绘制。
接口隔离原则和单一职责原则一样,涉及到粒度的问题,解决粒度大小,同样依赖于具体的业务场景,需要读者根据实践去权衡。

5、迪米特法则(最少知识原则)

迪米特法则(Law of Demeter)也叫最少知识原则,英文Least Knowledge Principle,简称LKP原则。其含义为:一个对象应该对其它对象有最少的了解。举例说明:一个公司有多个部门,每个部门有多个员工,如果公司CEO要下发通知给每个员工,是调用接口直接通知所有员工么?其实不然,CEO只需和它的“朋友”类部门Leader交流就好,部门Leader再下发通知信息即可。而CEO类不需要与员工进行“交流”。
迪米特法则要求对象应该仅对自己的朋友类交流,而不应该对非朋友类交流。那什么才是朋友类呢?一般来说,朋友类具有以下特征:
1)当前对象本身(self);
2)以参量形式传入到当前对象方法中的对象;
3)当前对象的实例变量直接引用的对象;
4)当前对象的实例变量如果是一个聚集,那么聚集中的元素也都是朋友;
5)当前对象所创建的对象。

6、开闭原则

开闭原则英文原名为Open Closed Principle,简称OCP原则。其含义为:一个软件实体,如类、模块、函数等,应该对扩展开放,对修改关闭。开闭原则是非常基础的一个原则,也有人把开闭原则称为“原则的原则”。前面讲到过,模块分原子模块,低层模块,高层模块,业务层可以认为是最高层次的模块。对扩展开放,意味着模块的行为是可以扩展的,当高层模块需求改变时,我们可以对低层模块进行扩展,使其具有满足高层模块的新功能;对修改关闭,即对低层模块行为进行扩展时,不必改动模块的源代码。最理想的情况是,业务变动时,仅修改业务代码,不修改依赖的模块(类、函数等)代码,通过扩展依赖的模块单元来实现业务变化。举例说明:假设一个原始基类水果类,苹果类是它的派生类,苹果中包含水果的各种属性,如形状、颜色等;另有两个类,农民类和花园类,最高层次(业务层次)为农民在花园种苹果。如果此时,农民决定不种苹果了,改种梨,符合OCP原则的设计应该为基于水果类构建一个新的类,即梨类(对扩展开放),而并不应该去修改苹果类,使它成为一个梨类(对修改关闭)。修改应仅在最高层,即业务层中进行。

二、遵循设计原则的好处

由于设计原则是设计模式的提炼,因而设计原则的好处与设计模式是一致的,即:代码易于理解;更适于团体合作;适应需求变化等。

三、设计原则与设计模式

1、创建类设计模式与设计原则

工厂模式:工厂方法模式是一种解耦结构,工厂类只需要知道抽象产品类,符合最少知识原则(迪米特法则);同时符合依赖倒置原则和里氏替换原则;
抽象工厂模式:抽象工厂模式具有工厂模式的优点,但同时,如果产品族要扩展,工厂类也要修改,违反了开闭原则;
模板模式:优秀的扩展能力符合开闭原则。

2、结构类设计模式与设计原则

代理模式:代理模式在业务逻辑中将对主体对象的操作进行封装,合适的应用会符合开闭原则和单一职责原则;事实上,几乎带有解耦作用的结构类设计模式都多少符合些开闭原则;
门面模式:门面模式不符合开闭原则,有时不符合单一职责原则,如若不注意,也会触碰接口隔离原则;
组合模式:符合开闭原则,但由于一般在拼接树时使用实现类,故不符合依赖倒置原则;
桥梁模式:桥梁模式堪称依赖倒置原则的典范,同时也符合开闭原则。

3、行为类设计模式与设计原则

策略模式:符合开闭原则,但高层模块调用时,不符合迪米特法则。行为类设计模式多少会符合些单一职责原则,典型的如观察者模式、中介者模式、访问者模式等;
责任链模式:符合单一职责原则和迪米特法则;
命令模式:符合开闭原则。

在不同的业务逻辑中,不同的设计模式也会显示出不同的设计原则特点,从这个意义上来说,设计模式是设计原则的体现,但体现不是固定的,是根据业务而有所不同的。

目录
相关文章
|
1天前
|
设计模式 开发者 Python
Python编程中的设计模式:工厂方法模式###
本文深入浅出地探讨了Python编程中的一种重要设计模式——工厂方法模式。通过具体案例和代码示例,我们将了解工厂方法模式的定义、应用场景、实现步骤以及其优势与潜在缺点。无论你是Python新手还是有经验的开发者,都能从本文中获得关于如何在实际项目中有效应用工厂方法模式的启发。 ###
|
3天前
|
设计模式 监控 数据库连接
Python编程中的设计模式之美:提升代码质量与可维护性####
【10月更文挑战第21天】 一段简短而富有启发性的开头,引出文章的核心价值所在。 在编程的世界里,设计模式如同建筑师手中的蓝图,为软件的设计和实现提供了一套经过验证的解决方案。本文将深入浅出地探讨Python编程中几种常见的设计模式,通过实例展示它们如何帮助我们构建更加灵活、可扩展且易于维护的代码。 ####
|
11天前
|
设计模式 开发者 Python
Python编程中的设计模式:从入门到精通####
【10月更文挑战第14天】 本文旨在为Python开发者提供一个关于设计模式的全面指南,通过深入浅出的方式解析常见的设计模式,帮助读者在实际项目中灵活运用这些模式以提升代码质量和可维护性。文章首先概述了设计模式的基本概念和重要性,接着逐一介绍了几种常用的设计模式,并通过具体的Python代码示例展示了它们的实际应用。无论您是Python初学者还是经验丰富的开发者,都能从本文中获得有价值的见解和实用的技巧。 ####
|
8天前
|
设计模式 开发者 Python
Python编程中的设计模式应用与实践###
【10月更文挑战第18天】 本文深入探讨了Python编程中设计模式的应用与实践,通过简洁明了的语言和生动的实例,揭示了设计模式在提升代码可维护性、可扩展性和重用性方面的关键作用。文章首先概述了设计模式的基本概念和重要性,随后详细解析了几种常用的设计模式,如单例模式、工厂模式、观察者模式等,在Python中的具体实现方式,并通过对比分析,展示了设计模式如何优化代码结构,增强系统的灵活性和健壮性。此外,文章还提供了实用的建议和最佳实践,帮助读者在实际项目中有效运用设计模式。 ###
10 0
|
11天前
|
设计模式 存储 数据库连接
Python编程中的设计模式之美:单例模式的妙用与实现###
本文将深入浅出地探讨Python编程中的一种重要设计模式——单例模式。通过生动的比喻、清晰的逻辑和实用的代码示例,让读者轻松理解单例模式的核心概念、应用场景及如何在Python中高效实现。无论是初学者还是有经验的开发者,都能从中获得启发,提升对设计模式的理解和应用能力。 ###
|
2月前
|
设计模式 Java 测试技术
Java设计模式-UML与设计原则(1)
Java设计模式-UML与设计原则(1)
|
2月前
|
设计模式
python24种设计模式
python24种设计模式
|
3月前
|
设计模式 XML 数据格式
python之工厂设计模式
python之工厂设计模式
python之工厂设计模式
|
3月前
|
设计模式 前端开发 JavaScript
React开发设计模式及原则概念问题之什么是HOC(Higher-order component),HOC遵循的设计原则都有哪些
React开发设计模式及原则概念问题之什么是HOC(Higher-order component),HOC遵循的设计原则都有哪些
|
3月前
|
设计模式 存储 数据库连接
Python设计模式:巧用元类创建单例模式!
Python设计模式:巧用元类创建单例模式!
45 0