💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
1、单一职责原则(SRP):一个类只实现一个功能;换一种说法,一个类只能有一个引起它变化的原因;在软件工程中有一个要求,叫做高内聚;一个类只实现一个功能,无凝内聚度是最高的了;这一原则可以使一个类更好地被重用;当然,“一个功能”是相对的,在某种情况下,MODEM功能是一个单一功能,而在另一种情况下,可能就要把MODEM功能再分解成多个小功能; 2、开放封闭原则(OCP):开放是指一个类能够扩展功能,封闭是指这个类对于功能修改是封闭的,也就是说不能修改其已有的代码和功能;要实现这一目标,关键是抽象;在客户类中只使用抽象基类,在应用中子类继承基类,并按实际需要扩展基类的功能;按更通俗的说法就是:接口不能改变,功能可以扩展; 3、子类替换原则(LSP):就是一个子类在任何情况下,都能替换掉它的基类;这是面向对象设计方法中实现继承和多态必须遵循的一条基本原则,显然也是开放封闭原则能够实现的基础;如何实现这一原则呢?那就是子类必须要有比基类相同或更弱的前置条件,相同或更强的后置条件;前置条件就是调用一个方法之前必须满足的条件,后置条件就是一个方法执行之满足的条件;为了更清楚地说明这一个问题,见下面的函数表达式: Y = F(X); F是一个函数,X是一个整型的输入参数,Y是一个整型的返回值,如果F要求X>0,返回值Y>1,则X>0和Y>1就分别是F的前置条件和后置条件;如果F是基类A中的一个函数,B是A的一个子类,并扩展了F的功能,则B类中F的前置条件必须跟A类中的相同或更弱,也就B类中的F必须至少能接受X>0,如果能同时接收X<=0的条件更好,但不能要求X>1,这是一个X>0更强的条件;B类中的F必须保证返回值Y>1,当然如果能保证Y>10更好,但不能使返回值Y<=1,这样就不满足A类中F返回值Y>1的条件;不满足子类替换原则最直接的后果就是使应用程序产生BUG;必须说明的是,在实际中是很难完全遵循子类替换原则的,必须作合理的假设,在这个假设的前提下遵循子类替换原则,这就是所谓契约设计; 4、依赖倒置原则(DIP):就是上层模块不能依赖于下层模块,两者都应该依赖抽象;抽象不能依赖细节,细节应该依赖于抽象;对这一原则要灵活看待,因为这一原则和当前开发中常用组件开发方式看起来是相矛盾的;首先明确定义一下上层模块和下层模块,所谓上层模块是调用别人的模块,也可称之为客户模块,下层模块是被别人调用的模块,也可称之为服务模块;显然这是一个相对的概念,因为一个模块很可能同时即调用别的模块,又被另外的模块调用;依赖倒置原则告诉我们客户模块和服务模块不能互相依赖,而只能依赖于一个抽象的基类;另外这个抽象基类的接口是由客户模块决定,而不是由服务模块决定;也就是说客户模块需要什么,服务模块就提供什么,而不是服务模块提供什么,客户模块就使用什么;这颇有点当前企业信奉的一个原则:客户就是上帝,客户需要什么,我们就提供什么;而我们当前常用的组件编程中,每一个组件都是一个被别人调用的具体类,显然是属于细节和服务模块,我们调用组件,实际上就依赖了这些组件的模块;根据依赖倒置原则是不是就不能调用这些组件呢?当然不能这么呆板,在设计中还有另一条原则,稳定依赖是没有害处的;说到底,这些组件也是根据客户需求制定出来的,只不过是已经固化了的需求;而且这些组件经过了严密测试,是稳定的,依赖它们没有害处;依赖倒置原则是针对我们自己的设计来说的;当然,如果我们自己设计的某一个服务类经过了严格的测试和大量的使用,都已经验证没有问题,也可以作为一个通用的组件,别人可以调用它,依赖它,没有问题; 5、接口隔离原则(ISP):这一原则好象是单一职责原则的升级版,接口隔离原则强调的是当一个服务类需要被即有共同功能需求又有不同功能需求的客户类使用时,不能在服务类中加进它的客户不需要的方法,比如在服务类A的客户中, B类客户需要F方法,而C类客户则不需要F方法,这时不能简单地把F方法加到服务类A中以满足B类客户的需求,而应分离接口;比如另设计一个服务类D,其中包含F方法,并把共用的功能委托给A实现,这样B客户可以使用D,而C客户继续使用A;对这一原则我有所保留的是:如果F方法对C类没有影响,直接加到A类中也无防,而且这种情况是很普遍; 6、共同封闭原则:这是针对包的;一个包对应用一个程序文件,包含一到多个类,这些类具有共同的封闭性,要么是都不能修改,要么是只能由同一原因引起修改; 7、共同重用原则:也是针对包的;不同类的通用性也是不一样的,通用性最高的就是在所有项目中都可使用,比如我们用到的集成开发工具中的组件;有些类可能包含些行业特征,只能这一行业类的软件中使用,有些类包含了某一个项目的特征,就可能在该项目中使用;但是一个包中的所有类的通用性都应该是一样的,这样才能保证包的重用度最大化;