Java 中的设计思想

[b]① 单一职责原则SRP[/b](Single Responsibility Principle)

所谓“单一职责”原则,就是,一个类应该仅有一个引起它变化的原因。多个职责,就是一个类有多个引起它变化的原因。

如果一个类有多个职责,会造成职责的相互影响,可能一个职责的变化,会影响到其他职责的的实现,甚至引起其他职责跟着变化,这种设计是很脆弱的。因为这样把多个职责耦合在一起了。

这个原则看起来简单,好理解,但是实际上很难完全做到,难点在于如何区分“职责”。这是个没有标准量化的东西,哪些算职责、到底这个职责有多大的粒度,如何细化等。因此,在实际开发中,这个原则也是最容易违反的。

[b]② 开放-关闭原则OCP[/b](Open-Closed Principle)

所谓“开放-关闭”原则,是指:一个类应该对扩展开放,对修改关闭。即:类的行为是可以扩展的,而且是在不修改已有代码的情况下进行扩展。开闭原则是设计中非常核心的一个原则。

实现开闭原则的关键在于合理地抽象、分离出变化与不变化的部分,为变化的部分预留下可扩展的方式,比如,钩子方法或是动态组合对象等。

这个原则看起来简单,但实际上一个系统要做到完全遵守开闭原则,几乎是不可能的,也没有这个必要。适度的抽象可以提高系统的灵活性,使其可扩展、可维护。如果过度地抽象会增加系统的复杂程度。应该在需要改变的地方应用开闭原则,而不用到处使用,从而陷入过度设计。

[b]③ 里氏替换原则LSP[/b](Liskov Substitution Principle)

所谓“里氏替换”原则,指的是,子类型必须能够替换掉它们的父类型。这是一种多态的使用情况,它可以避免在多态的应用中,出现某些隐蔽的错误。

事实上,当一个类继承了另外一个类,那么子类就拥有了父类中可以继承下来的属性和操作。理论上说,此时使用子类型去替换掉父类型,应该不会引起原来使用父类型的程序出现错误。

但是,很不幸的是,在某些情况下会出现问题。比如,如果子类型覆盖了父类类型中的某些方法,或者子类型修改了父类型的某些属性的值,那么原来使用父类型的程序就有可能出现错误,因为在运行期间,从表面上看,它调用的是父类型的方法,需要的是父类型方法实现的功能,但是实际运行调用的却是子类型覆盖实现的方法,而该方法与父类型的方法并不一样,于是导致错误的产生。

从另外一个角度来说,里氏替换原则是实现开闭的主要原则之一。开闭原则要求对扩展开放,扩展的一个实现手段就是使用继承;而里氏替换原则是保证子类型能够正确替换父类型,只有正确替换,才能实现扩展,否则扩展了也会出现错误。(如果程序中调用了父类型中的某些方法,而子类型覆盖了父类型的这些方法,那么这时程序中子类型就不能替换父类型。)

[b]④ 依赖倒置原则DIP[/b](Dependence Inversion Principle)

所谓“依赖倒置”原则,是指,依赖与抽象,不依赖于具体类。要做到依赖倒置,典型的应该做到:

■ 高层模块不应该依赖于底层模块,二者都应该依赖于抽象。

■ 抽象不应该依赖于具体实现,具体实现应该依赖于抽象。


很多人觉得,层次化调用的时候,应该是高层调用“底层所拥有的接口”,这是一种典型的误解。事实上,一般高层模块包含对业务功能的处理和业务策略的选择,应该被重用,是高层模块去影响底层的具体实现。

底层接口应该是高层提出的,而由底层实现。即底层接口的所有权在高层模块,这是一种所有权的倒置。这是著名的Hollyword 原则:Don't call us,We'll call you!

[b]⑤ 接口隔离原则[/b] ISP (Interface Segregation Principle)

所谓“接口隔离”原则,是指,不应该强迫客户依赖与他们不用的方法。

这个原则用来处理那些比较“庞大”的接口,这种接口通常会有较多的操作声明,涉及到很多职责。客户在使用这些接口的时候,通常会有很多他不需要的方法,这些方法对于客户来讲,就是一种“接口污染”,相当于强迫用户在一大堆“垃圾方法”中去寻找他需要的方法。因此,这样的接口应该被隔离,应该按照不同的客户需求来分离成针对客户的接口。这样的接口中,只包含客户需要的操作声明,这样即方便了客户的使用,也可以避免无用接口而导致的错误。

分离接口的方式,除了直接进行代码分离之外,还可以使用代理来分离接口,在能够支持多重继承的语言中,开可以采用多重继承的方式进行分离。

[b]⑥ 最少知识原则[/b] LKP(Least Knowledge Principle)

所谓“最少知识”原则,是指,只和你的朋友谈话。

这个原则用来指导我们在设计系统的时候,应该尽量减少对象之间的交互,对象只和自己的朋友交互,从而松散对象之间的耦合。通过松散对象之间的耦合,来降低对象之间的依赖,这样在修改系统的某一个部分的时候,就不会影响到其他的部分,从而使系统有更好的可维护型性。

什么样的对象才能当做“朋友”呢?

● 当前对象本身。

● 通过方法的参数传进来的对象。

● 当前对象所创建的对象。

● 当前对象的实例变量所引用的对象。

● 方法内所创建或实例化的对象。

[b]⑦ 其他原则[/b]

◆ 面向接口编程。

◆ 优先使用组合(聚合),而非继承。

◆ 一个类需要的数据应该隐藏在类得内部。

◆ 类之间应该零耦合,或只是传导耦合,即:对象之间要么没有关系,要么只使用另一个对象的接口提供的操作。

◆ 在水平方向上尽可能分布系统功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值