阿川CH
学海无涯,上栽上栽!
Toggle navigation
阿川CH
主页
归档
标签
软件设计原则SOLID
2018-03-27 09:36:30
0
0
0
cqc
# 软件设计原则 ## S:单一职责原则 > Single Responsibility Principle, 简称SRP。 老美的定义是这样的 > A class should have only one reason to change > 一个类改变它的原因有且只能是一个 单一职责应用在接口中还好操作,不过如果应用在类中就有点难了。类需要控制好粒度,比如下面的邮件例子,在开发初期完全没有问题,后面需要可能会要求支持内容的富文本形式或可能的其他形式,此时需要content抽像出来,不该content的改动而影响到Email这个类 ```java class Email { public void setSender(String sender) { // set sender; } public void setReceiver(String receiver) { // set receiver; } public void setContent(String content) { // set content; } } ``` 改动后为 ```java interface IContent{ String getStringAs(){ // } } class Email { public void setSender(String sender) { // set sender; } public void setReceiver(String receiver) { // set receiver; } public void setContent(IContent content) { // set content; } } ``` 在我看来,开发前期,可能业务并不复杂,有很多的类结构还算是合理的。随着业务发展,可能会越复杂,此时原来负责的类职责可能会产生分裂,比如上例中,原来email可能只要求简单文本,后面需要支持各种类型的文本后,需要把格式化文本的职责分离出去 ## O:开闭原则 > Open Close Principle, 简称OCP 定义如下 > Software entities like classes, modules and functions should be open for extension but closed for modifications. 软件实体如类、模块和函数都应该对扩展开放,对修改关闭。 ## L:里氏替换原则 > Liskov Substitution Principle, 简称LSP 有两种定义 > If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T. 如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型。 > Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it. 所有引用基类的地方必须能透明地使用其子类的对象。 这个原则说白了开发类(下称当前类)时,如需依赖与关联外部类时,最好是使用接口或基类,好让在实例化当前类时,能根据需求调整外部类的实现类,而无需改动当前类 ## I:接口隔离原则 > Interface Segregation Principle ,简称ISP 有两种定义 > Clients should not be forced to depend upon interfaces that they don' t use. 客户端不应该依赖它不需要的接口 > The dependency of one class to another one should depend on the smallest possible interface. 类间的依赖关系应该建立在最小的接口上 接口不可太臃肿,提供全能的服务,导致实现者需要实现自己不关心的功能或暴露给接口调用者许多调用者不关心的服务。 以下还是一个管理者和其工人的例子 ``` interface IWorker { public void work(); public void eat(); } class Worker implements IWorker{ public void work() { // ....working } public void eat() { // ...... eating in launch break } } class SuperWorker implements IWorker{ public void work() { //.... working much more } public void eat() { //.... eating in launch break } } class Manager { IWorker worker; public void setWorker(IWorker w) { worker=w; } public void manage() { worker.work(); } } ``` 工人能工作,也能吃,这在业务初始的时候是合理的。只是后来管理人员引入的机器人,但机器人不需要吃怎么办,难道需要强行实现吃的功能。此时基于业务,设计已经不合理,违背了**接口隔离原则**,需要做进一步的重构 ``` interface IWorker extends Feedable, Workable { } interface IWorkable { public void work(); } interface IFeedable{ public void eat(); } class Worker implements IWorkable, IFeedable{ public void work() { // ....working } public void eat() { //.... eating in launch break } } class Robot implements IWorkable{ public void work() { // ....working } } class SuperWorker implements IWorkable, IFeedable{ public void work() { //.... working much more } public void eat() { //.... eating in launch break } } class Manager { Workable worker; public void setWorker(Workable w) { worker=w; } public void manage() { worker.work(); } } ``` 在遵从**接口隔离原则**时,还需满足**职责单一原则** ## D:依赖倒置原则 > Dependence Inversion Principle, 简称DIP 定义如下 > High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions. 高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。 `低层模块`指的是粒度更细的操作,比如对操作系统的复制、删除文件等。`高层模块`则是对低层模块的组合,并加入复杂的操作逻辑。如果`高层模块`直接依赖于`低层模块`,当`低层模块`的需求有变化时,将会导致`高层模块`也需要跟着改动,造成`高层模块`的不稳定。比如下面的一个例子 ```java class Worker { public void work() { // ....working } } class Manager { Worker worker; public void setWorker(Worker w) { worker = w; } public void manage() { worker.work(); } } class SuperWorker { public void work() { //.... working much more } } ``` 由于需要调整,需要将原来的`Worker`调整为`SuperWorker`,则不得不改动到`Manager`的代码, 好的设计是,不论上层还是下层都是要面向抽象的,以上例子可以做如下修改 ```java interface IWorker { public void work(); } class Worker implements IWorker{ public void work() { // ....working } } class SuperWorker implements IWorker{ public void work() { //.... working much more } } class Manager { IWorker worker; public void setWorker(IWorker w) { worker = w; } public void manage() { worker.work(); } } ```
上一篇:
Hive技巧:通过增加冗余分区来简化sql复杂度,提高并行度
下一篇:
hive能查出数据而presto查不出数据的原因
文档导航