返回

设计原则

单一职责原则

当设计封装一个类时,该类应该只负责一件事。

通过不断地进行**“类重构”**,将类中与实现相关功能的部分抽取出来,另外封装为新的类,之后再利用组合的方式将新增的类加入到原类中,慢慢就能符合类单一职责化的要求。

在完成功能后在每个类的上方添加注释,如果能够轻松描述类的功能,则可以视为满足单一职责。

开闭原则

对扩展开放、对修改关闭

当增加系统功能的需求发生时,需要对**“功能的增加保持开放”**。为了慢则这个原则的需求,系统分析时就要朝向**“功能接口化”**的方向进行设计,将系统功能的**“操作方法”**向上提升,抽象化为**“接口”**,将**“功能的实现”**向下移到子类中。因此,在面对增加系统功能的需求时,就可以试用**“增加子类”**的方式来满足。

在完成功能后在每个类的上方添加注释,如果能够轻松描述类的功能,则可以视为满足单一职责

里氏替换原则

子类必须能够替换父类

照这个原则去实现一个有多层继承的类群组,那么其中的父类通常是**“接口类”**或**“可被继承的类”**。父类中一定包含了可被子类重新实现的方法,而客户端试用的操作接口也是由父类来定义的。

==客户端在使用的过程中,必须不能使用到“对象强制转换为子类”的语句,客户端也不应该知道,目前使用的对象是哪一个子类实现的。==至于使用那个子类的对象来替代父类对象,则是由类本身的对象产生机制来决定,外界无法得知。

依赖倒置原则

1. 高层模块不应该依赖于低层模块,两者都应该依赖于抽象概念;

2.抽象接口不应该依赖于实现,而实现应该依赖于接口抽象。

以计算机为例,高层定义了计算机的USB接口,这个接口定义了硬件所需的规格及软件驱动程序的编写规则。只要任何低层模块,例如存储卡、U盘、鼠标等符合USB接口规范,都能加入计算机的模块中。

上述计算机的例子足以说明如何由“高层模块定义接口”再由“低层模块遵循这个几口实现”的过程。

当这个过程依赖关系反转也说明了第二项原则主题的含义:“抽象不应该依赖实现,而实现应该依赖于抽象接口”。当高层模块定义了沟通接口之后,与底层模块的沟通只能通过接口来进行,在具体实现上,这个接口可能是以一个类的变量或对象引用来表示的。

在使用变量或对象引用的过程中,不能做出任何的类型转换,因为这样做就限定了高层模块只能使用某一个低层的特定实现。而且,子类在重新实现时,都要按照接口类所定义的方法进行实现,不应该再新增其他方法,让高层模块有利用类型转换的方式去调用的机会。

接口隔离原则

客户端不应该被迫使用他们用不到的接口

当项目中出现了一个负责主要功能的类,而且这个类还必须负责跟其他子系统进行沟通时,针对每一个子系统的需求,主要类就必须增加对应的方式。但是,增加越多的方法就等同于增加类的接口复杂度。因此,每当要使用这个类的方法时,就要小心的从中选择正确的方法,无形之中增加了开发和维护的困难度。

通过**“功能切分”**和**“接口的简化”**可以减少这类问题的发生,或者运用设计模式来重新规划类,也可以减少不必要的操作接口出现再类中

最少知识原则

一个类越少使用到其他类提供能的功能越好

意思是,当这个类能够只靠本身的“知识”去完成功能的话,那么就相对地减少于其他子对象“知识”的依赖度。这样的好处是减少了这个类与其他类的耦合度。

少用继承多用组合原则

当子类继承一个**“接口类”**后,新的子类就要负责重新实现接口类中所定义的方法,而且不该额外扩充接口,以上符合多个设计原则的需求。但有时只需要子类提供的功能,并不想额外知道父类的功能,因为这样会增加程序设计挑选方式时的难度。

“闹钟类”可以利用继承“时钟”的方式,取得“时间功能”方法的实现,只要子类本身再另外加上“定时提醒”的功能,就能实现“闹钟功能”的目标。而从“时钟父类”上继承而来的其他方法对于闹钟来说,是多余的。

如果将设计改为在闹钟的类定义中,声明一个为时钟类的“类成员”,那么就可以减少不必要的方法出现的在闹钟接口上,也可以减少“闹钟类”的客户端对“时钟类”的依赖性