随心而作 2019-11-02
六大设计原则
1. 单一职责原则:对于一个类,应该只有一个引起它变化的原因;【功能内聚】
2. 里氏代换原则:子类必须能够替换掉它们的父类型;【减小继承耦合】
3. 开放-封闭原则:对于扩展是开放的;对于修改是封闭的。
4. 依赖倒置原则:程序的高层模块不应该依赖于底层模块,两者应依赖于抽象;抽象不应该依赖于具体斜街,而细节应该依赖于抽象。【面向接口编程,而不是针对实现编程】【耦合具有方向性差异,稳定与变化之间的耦合,接口稳定而具体易变化】
5. 合成/聚合复用原则:尽量不使用类继承,而尽量使用合成/聚合【避免类爆炸】
6. 迪米特法则:如果两个类之间不必直接通信,则这个类不应该发生直接相互作用。如果其中一个类需要调用另一个类的某个方法,可以通过第三方转发这个调用。【体现在顺序图中,跨“朋友/友元”调用“陌生”对象,进行改进】
一、单一职责原则
举例:超人只维护世界
原因:易于维护和高度的可复用性是面向对象开发的比较突出的两个优点。若职责过于庞大,则维护困难,可复用性也随之降低,与面向对象的思想背道而驰。
好处:降低类的复杂度,一个类只负责一项职责,其逻辑肯定比负责多项职责简单;提高类的可读性,提高系统的可维护性。
二、里氏代换原则
举例:超人只维护世界
符合:鲨鱼是鱼,老木匠徒弟替老木匠打家具;
违反:正方形是长方形【如何修改,构造一个抽象的四边形类】
作用:使得使用父类类型的模块在无需修改的情况下,就可以通过使用不同的子类拓展。里氏代换规则是对实现抽象化的具体步骤的规范。【里氏代换原则是对开闭原则的进一步规范】
三、开放-封闭原则(OCP)----面向对象设计的主要目标
原因:封装变化、降低耦合
效果:开闭原则提供了一个使系统在面对需求变更时,可以保持系统相对稳定的解决方案。
举例:
符合:动物-猫-咪咪(继承/多态复用,并拓展)
对比:
1. 银行业务员(存款、取款、转账、进行基金申购)
2. 银行业务员接口,存款业务员、取款业务员、负责转账业务员、基金业务员
//其实这里的改写也体现了单一职责原则,依赖于抽象的银行业务员接口利于扩展
核心思想:只依赖于抽象,面向抽象编程,而不是面向具体编程。【通过抽象来隔离变化】
四、依赖倒置原则(DIP)----面向对象设计的主要机制
关键:实现抽象化,并且从抽象化得出具体的实例。
本质:通过抽象(接口或者抽象类)使各个类或模块的实现彼此独立,不相互影响,从而实现模块之间的松散耦合。
举例:
对比:
1. Worker<--Manager,新增SeniorWorker类. //必不可少的导致了需要对Manager类进行修改
2. Worker implements IWorker, IWorker <--Manager //依赖抽象
符合:模板设计模式
小结:
依赖倒置,倒置的是什么依赖?【相较于传统的过程性设计而言】
答:从复用的角度来说,高层次的模块使应当被复用的,而且会是复用的重点,因为它包含有一个应用系统最重要的宏观逻辑,并且较为稳定。而在传统的过程性设计中,复用则侧重于具体层次模块的复用。
上层类不直接使用底层类,他们使用接口作为抽象层,在该情况下,上层类中创建底层类的对象时不允许使用new关键字。可以使用一些创建型设计模式,例如工厂方法、抽象工厂和原型模式【Spring中使用依赖注入/自动装配的方式】
五、合成/聚合复用原则
面向对象中复用的联众基本方法:
1. 通过合成/聚合,即合成//聚合复用原则(CARP)
2. 通过继承
合成/聚合:
聚合便是比较弱的拥有关系,“Has-A”
合成是一种特殊的聚合关系,体现严格的整体与部分的关系【部分与整体同生命周期,整体死亡,部分不复存在】。
可通过继承复用的标准:里氏代换规则
举例:
违反:人,管理员、普通员工、大学生 extends 人【管理员、普通员工和大学生都是一种角色,人可以拥有角色的聚合】
聚合的例子:将军和士兵
合成的关系:皇帝和大臣【一种更强的拥有关系,皇帝可以决定将军的生死】
优点:
1. 新对象存取子对象的唯一方法是通过子对象的接口;
2. 这种复用是黑盒的复用,因为子对象的内部细节是新对象所看不见的;
3. 这种复用更好地支持封装的特性;
4. 这种复用是线上的相互依赖性是比较小的;
5. 每一个新的类都可以将焦点集中在一个任务上。
6. 这种复用可以在运行时动态进行,新的对象可以动态地引用与子对象类型相同的对象。
7. 作为复用手段几乎可以应用到任何环境中去。
缺点:
有较多的对象需要管理
六、 迪米特法则----不要和陌生人说话
设计初衷:降低类之间的耦合,尽可能使系统的功能模块相互独立,相互之间不存在或者很少存在依赖关系。
缺点:倒置系统中存在大量的中介类,这些类的存在完全是为了传递类之间的相互调用关系--这在一定程度上会增加系统的复杂度。
前提:类的结构设计上,每个类都应该建底成员的访问权限,类自己包装好自己的private状态,不需要让别的类知道的字段或者行为就不要公开。
根本思想:强调类之间需要尽量多实现松散耦合,类之间的耦合越弱越有利于复用。
举例:
对比:
1. 皇帝直接召见御前侍卫
2. 皇帝->圣旨->相关机构(传递圣旨)->御前侍卫->太监(引路)->安全检查的专门人员->皇帝身边的人->皇帝