1、单一职责原则(Single Responsibility Principle)
定义 : 应该有且只有一个原因引起类的变化
注意 : 这里的类不光指类,也适用于方法和接口,比如我们常说的一个方法实现一个功能。
?单一职责原则告诉我们:一个类不能太“累”!在软件系统中,一个类(大到??椋〉椒椒ǎ┏械5闹霸鹪蕉?,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生改变则可将它们封装在同一类中。
?单一职责原则是实现高内聚、低耦合的指导方针,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关实践经验。
2、里氏代换原则(Liskov Substitution Principle)
定义 : 只要父类出现的地方子类就一定可以出现,而且替换为子类也不会出现任何异?;虼砦?使用者不需要知道是父类还是子类.但是返回来就不行了,有子类出现的地方,不一定能使用父类。
使用规范 :?
子类必须完全实现父类的方法,如果子类无法完全实现父类的方法,则建议断开父子继承关系,采用依赖 | 聚集 | 组合 等关系来代替。
子类可以有自己的个性
覆盖或实现父类的方法时,输入参数可以被放大,比如父类中有一个方法的输入参数是 HashMap,子类的参数可以是 Map 类型,这样父类就可以被子类替换,如果反过来,则违背了里氏替换原则,所以子类中方法的前置条件必须与父类的被覆写的方法的前置条件相同或者更宽松覆写或实现父类的方法时,输出结果可以被缩小,也就是说如果父类方法返回的类型 T,子类的相同方法(重载或覆写)的返回值类型 S,S 和 T 要么同类型,要么 S 是 T 的子类;跟上面的道理一样。
注意 : 采用里氏替换原则时,尽量避免子类的"个性",一旦子类有了"个性",子类和父类的关系就会变得不好调和。
3、依赖倒置原则(Dependence Inversion Principle)
定义 : 依赖倒置原则包含三个含义
高层??椴挥Ω靡览档筒隳??两者都应该依赖其抽象
抽象不应该依赖细节
细节应该依赖抽象
高层模块和低层??楸冉虾美斫?每一个逻辑都是由原子逻辑组成的,不可分割的原子逻辑是低层???原子逻辑再组装就是高层???
抽象指的是接口或者抽象类,两者都不能直接实例化;
细节就是实现类,实现接口或继承抽象类而产生的类就是细节,其特点是可以被实例化;
依赖倒置原则在 Java 中的实现是表现是:
模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的;
接口或抽象类不依赖于实现类
实现类依赖接口或抽象类
这也是面向接口编程的精髓之一
遵循的规则 :?
每个类尽量都有接口或抽象类,或者两者都有
变量的表面类型尽量是接口或者抽象类
任何类都不应该从具体类派生
尽量不要覆写基类的方法,如果基类是一个抽象类,而且这个方法已经实现了,子类尽量不要覆写
结合里氏替换原则使用
接口负责定义 public 属性和方法,并且声明与其他对象的依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑
4、接口隔离原则(Interface Segregation Principle)
我们先来看接口的定义 :?
实例接口 : 在 Java 中声明一个类,然后用 new 关键字产生一个实例,它是对一类事物的描述,可以看成是一个接口
类接口 : 使用 interface 定义的接口
隔离的的理解 :?
客户端不应该依赖它不需要的接口
类之间的依赖关系应该建立在最小的接口上
概括 : 建立单一接口,不要建立臃肿庞大的接口,也就是接口尽量细化,接口中的方法尽量少
这个是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。
接口隔离原则的约束条件?:?
接口要高内聚,意思就是提高接口,类,模块的处理能力,减少对外的交互,再具体一点就是在接口中尽量减少对外的 public 方法,通过业务逻辑压缩接口中的 public 方法。
定制服务,就是单独为一个个体提供优良的服务,比如我们写用户??榈氖焙?需要给用户提供查询信息,修改密码,注册用户等信息,当管理员执行相同操作的时候,一般人会复用这些方法,然后在这个的基础上再增加管理员自己的方法,这种设计方法肯定是有问题的,这样设计,当你修改了普通用户调用的接口实现时,管理员的实现也会发生不可预测的改变,我们应该为管理员单独写一个接口。
接口设计是有限度的,接口的设计粒度越小,系统越灵活,这是肯定的,但灵活的同时带来的问题是 结构复杂化,开发难度增加, 可维护性降低。
一个接口只服务于一个子模块或业务逻辑,已经被污染了的接口,尽量去修改 ,若修改的风险较大,则采用适配器模式进行转化处理。
了解环境,拒绝盲从,不要一味的去套设计模式,有的时候不用比用了更好,也不要去照搬别人的设计方法,他的方法到你这不一定效果就好,毕竟业务逻辑不一样。
5、迪米特法则(Demeter Principle)
定义 : 迪米特法则也叫最少知识原则,含义是 一个对象应该对其他对象有最少的了解,这个应该很好理解,就是降低各??橹涞鸟詈?/p>
?如果一个系统符合迪米特法则,那么当其中某一个??榉⑸薷氖?,就会尽量少地影响其他???,扩展会相对容易,这是对软件实体之间通信的限制,迪米特法则要求限制软件实体之间通信的宽度和深度。迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系。
迪米特法则还有几种定义形式,包括:不要和“陌生人”说话、只与你的直接朋友通信等,在迪米特法则中,对于一个对象,其朋友包括以下几类:
(1) 当前对象本身(this);
(2) 以参数形式传入到当前对象方法中的对象;
(3) 当前对象的成员对象;
(4) 如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友;
(5) 当前对象所创建的对象。
????? 任何一个对象,如果满足上面的条件之一,就是当前对象的“朋友”,否则就是“陌生人”。在应用迪米特法则时,一个对象只能与直接朋友发生交互,不要与“陌生人”发生直接交互,这样做可以降低系统的耦合度,一个对象的改变不会给太多其他对象带来影响。
迪米特法则要求我们在设计系统时,应该尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。
在将迪米特法则运用到系统设计中时,要注意下面的几点:在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类造成太大波及;在类的结构设计上,每一个类都应当尽量降低其成员变量和成员函数的访问权限;在类的设计上,只要有可能,一个类型应当设计成不变类;在对其他类的引用上,一个对象对其他对象的引用应当降到最低。
6、开闭原则(Open Close Principle)
定义 : 一个软件实体如类,??楹秃Ω枚岳┱箍?对修改关闭,开闭原则也是其他五个原则的基石
在开闭原则的定义中,软件实体可以指一个软件???、一个由多个类组成的局部结构或一个独立的类。
????? 任何软件都需要面临一个很重要的问题,即它们的需求会随时间的推移而发生变化。当软件系统需要面对新的需求时,我们应该尽量保证系统的设计框架是稳定的。如果一个软件设计符合开闭原则,那么可以非常方便地对系统进行扩展,而且在扩展时无须修改现有代码,使得软件系统在拥有适应性和灵活性的同时具备较好的稳定性和延续性。随着软件规模越来越大,软件寿命越来越长,软件维护成本越来越高,设计满足开闭原则的软件系统也变得越来越重要。
为了满足开闭原则,需要对系统进行抽象化设计,抽象化是开闭原则的关键。在Java、C#等编程语言中,可以为系统定义一个相对稳定的抽象层,而将不同的实现行为移至具体的实现层中完成。在很多面向对象编程语言中都提供了接口、抽象类等机制,可以通过它们定义系统的抽象层,再通过具体类来进行扩展。如果需要修改系统的行为,无须对抽象层进行任何改动,只需要增加新的具体类来实现新的业务功能即可,实现在不修改已有代码的基础上扩展系统的功能,达到开闭原则的要求。