合成复用原则(Composite/Aggregate Reuse Principle,CARP)是指尽量使用对象组 合(has-a)/聚合(contanis-a),而不是继承关系达到软件复用的目的。可以使系统更加灵 活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较少。
继承我们叫做白箱复用,相当于把所有的实现细节暴露给子类。组合/聚合也称之为黑箱 复用,对类以外的对象是无法获取到实现细节的。要根据具体的业务场景来做代码设计, 其实也都需要遵循 OOP 模型。
demo:
文章,数据库操作。两个各自的对象封装。
文章不应该继承数据库类来达到数据的增删改查,而是通过聚合,实例化数据库类来直接使用。当然不同的数据库应该中间有个抽象层,底层有选择来决定调用那个数据库。
任何基类可以出现的地方,子类一定可以出现。里氏替换原则是继承复用的基石,只有当衍生类可以替换基类,软件单位的功能不受到影响时,即基类随便怎么改动子类都不受此影响,那么基类才能真正被复用
这就要求必须以下的规则:
优点:
代码共享,即公共代码被抽到父类。
提高代码重用性。
子类在父类的基础上可以有自己的特性。
提高代码的扩展性。
缺点:
侵入性。一旦继承,父类全部属性和方法都被子类拥有
约束性。子类需要拥有父类的属性和方法,子类多了一些约束。
耦合性。父类出现修改情况时,需要考虑子类的修改。
现实中的demo:
比如你在数据库操作模型中写了一个基类的 查询。理论上这个查询只要继承了这个基类所有models都可以调用,所以子类调用的时候,如果子类重写了该方法并且更改了原来的功能。这个继承就变得不在有意义。
定义:
又叫最少知道原则,如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。
作用:
其目的是降低类之间的耦合度,提高模块的相对独立性。
反作用:
增加了系统的复杂度
定义:
高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。其核心思想是:要面向接口编程,不要面向实现编程。依赖倒置原则是实现开闭原则的重要途径之一,它降低了客户与实现模块之间的耦合。
作用:
依赖倒置原则可以降低类间的耦合性;
依赖倒置原则可以提高系统的稳定性;
依赖倒置原则可以减少并行开发引起的风险;
依赖倒置原则可以提高代码的可读性和可维护性;
demo:
员工A 要给 员工B发送消息通知
最开始,我们发送消息的方法用的是通过邮件发送。发送动作是高层模块,邮件发送是底层模块。当有一天邮件模块不可用了,需要通过短信发送。 这个适合 原来高层模块无法发送。因为不支持短信。要是直接改邮件发送模块很显然不是对的。
优化方案:
中间加一层发送的抽象类接口。 高级发送模块只需要依赖与这个抽象类,而底层模块也应该依赖于这个抽象类。当更改了发送方案的情况下,只需要让不同的抽象类调用底层的发送接口即可。
定义:
接口隔离原则(Interface Segregation Principle,ISP)的定义是客户端不应该依赖它不需要的接口,类间的依赖关系应该建立在最小的接口上。简单来说就是建立单一的接口,不要建立臃肿庞大的接口。也就是接口尽量细化,同时接口中的方法尽量少。
接口隔离原则必须先满足单一原则。这里的接口单一指的是业务上的接口单一,单一原则指的是职责上的单一。
特点:
将臃肿庞大的接口分解为多个粒度小的接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
概念
一个类应该只负责一个职责,当一个类同时负责多个职责的时候,某个职责发生变动可能会影响整个类或者其他类的使用。
实际开发中,应该是尽量一个类只负责一个职责。同样一个方法,函数也应该只负责某项功能。
特点:
降低类(代码)的复杂度;
降低变更引起的风险;
减少影响范围,系统更稳定。
demo:
比如订单类应该只处理跟订单相关逻辑,而不要处理和用户相关的逻辑。
比如在laravel model开发中,user 的model应该只有跟用户相关的处理,不同的对象应该创建不同的model;
比如控制器,同对象的控制器可以用一个控制器,而不要所有的逻辑都到一个控制器去处理;