2016-12-28 迪米特法则+依赖倒转原则+里氏替换原则


依赖倒转原则

依赖倒转原则,也翻译成依赖倒置原则,抽象不应该依赖细节,细节应该依赖于抽象,要针对接口编程,而不是对实现编程。如电脑中无论主板、cpu、内存、硬盘都是针对接口设计的,PC电脑硬件的发展,和面向对象思想发展是完全类似的。

依赖倒转原则(为什么称为倒转呢,因为传统的设计中底层提供接口,高层根据底层的接口实现功能

A.高层模块不应该依赖底层模块,两个都应该依赖抽象。

B.抽象不应该依赖细节,细节应该依赖抽象。

若高层与底层都根据依赖倒转原则来编程,则可以提高代码复用能力,底层的更改不会对高层产生影响。


里氏代换原则

里氏代换原则:一个软件实体如果使用的是一个父类的对象的话,那么一定适用于其子类的对象,而且他察觉不出父类对象和子类对象的区别。也就是说,在软件里面,把父类都替换成她的子类,程序的功能不受影响。

里氏代换原则(LSP):子类必须能够替换掉他们的父类型。

正是由于有了这个原则,使得继承复用成为可能,只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。

正是由于可替代性才使得使用父类类型的模块在无需修改的情况下就可以扩展。


迪米特法则/最少知识原则

talk only to your immediate friends

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

迪米特法则首先强调的是在类的结构设计上,每一个类都应当尽量降低成员的访问权限,迪米特法则其根本思想,是强调了类之间的松耦合。类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。

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


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

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

有兴趣可以研究一下设计模式的门面模式Facade)等,都是迪米特法则应用的例子。这一法则却不仅仅局限于计算机领域,在其他领域也同样适用。比如,美国人就在航天系统的设计中采用这一法则。


狭义的迪米特法则

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

朋友圈的确定,“朋友”条件:

1)当前对象本身(this)

2)以参量形式传入到当前对象方法中的对象

3)当前对象的实例变量直接引用的对象

4)当前对象的实例变量如果是一个聚集,那么聚集中的元素也都是朋友

5)当前对象所创建的对象

任何一个对象,如果满足上面的条件之一,就是当前对象的“朋友”;否则就是“陌生人”。

狭义的迪米特法则的缺点:

在系统里造出大量的小方法,这些方法仅仅是传递间接的调用,与系统的商务逻辑无关。

遵循类之间的迪米特法则会是一个系统的局部设计简化,因为每一个局部都不会和远距离的对象有直接的关联。但是,这也会造成系统的不同模块之间的通信效率降低,也会使系统的不同模块之间不容易协调。


广义的迪米特法则在类的设计上的体现:

优先考虑将一个类设置成不变类。

尽量降低一个类的访问权限。

谨慎使用Serializable。

尽量降低成员的访问权限。



迪米特法则

Law of DemeterLoD

最少知识原则

Least KNowledge PrincipleLKP

一个对象应该对其他对象有最少的了解。通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没关系,那是你的事情,我就知道你提供的public方法,我就调用这么多,其他的一概不关心。

只和朋友交流

朋友间也是有距离的

一个类公开的public属性方法越多,修改时涉及的面也就越大,变更引起的风险扩散也就越大。因此,为了保持朋友类间的距离,在设计时需要反复衡量:是否还可以再减少public方法属性,是否可以修改为private、package-private(包类型,在类、方法、变量前不加访问权限,则认为包类型)、protected等访问权限,是否可以加上final关键字等。

注意:迪米特法则要求类“羞涩”一点,尽量不要对外公布太多的public方法和非静态的public变量,尽量内敛,多使用private、package-private、protected等访问权限。

是自己的就是自己的

如果一个方法放在本类中,既不增加类间关系,也对本类不产生负面影响,就放置在本类中。


最少知识原则、迪米特法则、Least KNowledge

要减少对象之间的交互,只留下几个“密友”,只和你的密友谈话。

当你设计一个系统,不管是任何对象,都要注意他所交互的类有哪些,并注意他和这些类是如何交互的。这个原则希望我们在设计中,不要让太多的类耦合在一起,免得修改系统中一部分,会影响到其他部分。

究竟怎样才能避免这样呢,就任何对象而言,在该对象的方法那,我们只应该调用属于以下范围的方法

该对象本身的方法

被当作方法的参数而传递进来的对象的方法

方法所创建或实例化的任何对象的方法

对象的任何组件(HAS-A关系)的方法

注意此原则告诉我们,如果某对象是调用其他的方法返回的结果,则不应调用该对象的方法,这样就要求了解此类对象,则本对象会与此对象发生耦合。


public class Car {

Engine engine; // 这是类的一个组件,我们能够调用他的方法

// 其他实例变量......

public Car() {

// 初始化发动机

}

public void start(Key key) {

Doors doors = new Doors(); // 在这里创建了一个新的对象,他的方法可以被调用

boolean authorized = key.turns(); // key是作为参数传进来的对象,其方法可以被调用

if(authorized) {

engine.start(); // 可以调用对象组件的方法

updateDashboarddisplay(); // 可以调用一个对象内的本地方法(local method)

doors.lock(); // 可以调用你所创建或实例化的对象的方法

}

}

public void updateDashboarddisplay() {

// 更新显示

}

}


最少知识原则也叫做迪米特法则,或则墨忒[tēi]耳法则(Law of Demeter)。很多人更倾向于使用原则来称呼他,法则的感觉太强,任何原则都应该是在有帮助的时候才遵守。所有的设计都不免需要折中。虽然原则提供了方针,但是在采用原则之前,必须全盘考虑所有的因素。

此原则虽然减少了对象之间的依赖,研究显示会减少软件的维护成本;但采用这个原则也会导致更到的“包装”类被制造出来,以处理和其他组件的沟通,这可能导致复杂度和开发时间的增加,并降低运行似的性能

总结:

当需要使用一个现有的类而其接口不符合你的需要时,就使用适配器。

适配器改变接口以符合用户的期望。

实现适配器可能需要一番功夫,也可能不费工夫,视目标接口的大小与复杂度而定。

适配器模式有两种形式:对象适配器和类适配器。类适配器需要用到多重继承。


当需要简化并统一一个很大的接口或者一群复杂的接口时,使用外观。

外观将客户从一个复杂的子系统中解耦,

实现一个外观,需要将子系统组合进外观中,然后将工作委托给子系统执行。

你可以为一个子系统实现一个以上的外观。


适配器将一个对象包装起来以改变其接口;装饰者将一个对象包装起来以增加新的行为和责任;而外观将一群对象“包装”起来以简化其接口。

相关文章

迭代器模式(Iterator)迭代器模式(Iterator)[Cursor]意图...
高性能IO模型浅析服务器端编程经常需要构造高性能的IO模型,...
策略模式(Strategy)策略模式(Strategy)[Policy]意图:定...
访问者模式(Visitor)访问者模式(Visitor)意图:表示一个...
命令模式(Command)命令模式(Command)[Action/Transactio...
生成器模式(Builder)生成器模式(Builder)意图:将一个对...