如何提高代码的扩展性(4)

简介: 如何提高代码的扩展性(4)

指导建议:使用者先定义接口


image.png


(3)里氏替换原则


image.png


如上图释义,一个软件实体如果使用的是一个基类的话,那么一定适用于其子类,而且它根本不能察觉出基类对象和子类对象的区别。


比如,假设有两个类,一个是Base类,另一个是Child类,并且Child类是Base的子类。那么一个方法如果可以接受一个基类对象b的话:method1(Base b)那么它必然可以接受一个子类的对象method1(Child c).


里氏替换原则是继承复用的基石。只有当衍生类可以替换掉基类,软件单位的功能不会受到影响时,基类才能真正的被复用,而衍生类也才能够在基类的基础上增加新的行为。


问题由来:有一功能P1,由类A完成。现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成。新功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,有可能会导致原有功能P1发生故障。


解决方案:当使用继承时,遵循里氏替换原则。类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法。


里氏替换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。它包含以下4层含义:

  • 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。

  • 子类中可以增加自己特有的方法。

  • 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。

  • 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

(4)依赖倒置原则


官方释义:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。


    上面的定义主要包含两次意思:

   1)高层模块不应该直接依赖于底层模块的具体实现,而应该依赖于底层的抽象。换言之,模块间的依赖是通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的。


    2)接口和抽象类不应该依赖于实现类,而实现类依赖接口或抽象类。这一点其实不用多说,很好理解,“面向接口编程”思想正是这点的最好体现。


image.png


相比传统的软件设计架构,比如我们常说的经典的三层架构,UI层依赖于BLL层,BLL层依赖于DAL层。由于每一层都是依赖于下层的实现,这样当某一层的结构发生变化时,它的上层就不得不也要发生改变,比如我们DAL里面逻辑发生了变化,可能会导致BLL和UI层都随之发生变化,这种架构是非常荒谬的!好,这个时候如果我们换一种设计思路,高层模块不直接依赖低层的实现,而是依赖于低层模块的抽象,具体表现为我们增加一个IBLL层,里面定义业务逻辑的接口,UI层依赖于IBLL层,BLL层实现IBLL里面的接口,所以具体的业务逻辑则定义在BLL里面,这个时候如果我们BLL里面的逻辑发生变化,只要接口的行为不变,上层UI里面就不用发生任何变化。


在三层架构里面增加一个接口层能实现依赖倒置,它的目的就是降低层与层之间的耦合,使得设计更加灵活。从这点上来说,依赖倒置原则也是“松耦合”设计的很好体现。

相关文章
|
5月前
|
消息中间件 存储 负载均衡
|
5月前
|
算法 Linux C++
C++框架设计中实现可扩展性的方法
在软件开发中,可扩展性至关重要,尤其对于C++这样的静态类型语言。本文探讨了在C++框架设计中实现可扩展性的方法:1) 模块化设计降低耦合;2) 使用继承和接口实现功能扩展;3) 通过插件机制动态添加功能;4) 利用模板和泛型提升代码复用;5) 遵循设计原则和最佳实践;6) 应用配置和策略模式以改变运行时行为;7) 使用工厂和抽象工厂模式创建可扩展的对象;8) 实现依赖注入增强灵活性。这些策略有助于构建适应变化、易于维护的C++框架。
360 2
|
5月前
|
中间件 微服务 缓存
中间件性能和可扩展性
【6月更文挑战第1天】
69 9
|
6月前
|
存储 分布式计算 负载均衡
HadoopHDFS的特点可扩展性
【5月更文挑战第11天】HadoopHDFS的特点可扩展性
125 1
|
6月前
|
监控 中间件
选择中间件性能和可扩展性
【5月更文挑战第20天】
64 1
|
5月前
|
敏捷开发 存储 缓存
【DDIA笔记】【ch1】 可靠性、可扩展性和可维护性 -- 可维护性
【6月更文挑战第4天】本文探讨了Twitter面临的一次发推文引发的巨大写入压力问题,指出用户粉丝数分布是决定系统扩展性的关键因素。为解决此问题,Twitter采用混合策略,大部分用户推文扇出至粉丝主页时间线,而少数名人推文则单独处理。性能指标包括吞吐量、响应时间和延迟,其中高百分位响应时间对用户体验至关重要。应对负载的方法分为纵向和横向扩展,以及自动和手动调整。文章强调了可维护性的重要性,包括可操作性、简单性和可演化性,以减轻维护负担和适应变化。此外,良好设计应减少复杂性,提供预测性行为,并支持未来改动。
56 0
|
5月前
|
缓存 关系型数据库 数据库
【DDIA笔记】【ch1】 可靠性、可扩展性和可维护性 -- 可扩展性
【6月更文挑战第3天】可扩展性关乎系统应对负载增长的能力,但在产品初期过度设计可能导致失败。理解基本概念以应对可能的负载增长是必要的。衡量负载的关键指标包括日活、请求频率、数据库读写比例等。推特的扩展性挑战在于"扇出",即用户关注网络的广度。两种策略包括拉取(按需查询数据库)和推送(预计算feed流)。推送方法在推特案例中更为有效,因为它减少了高流量时的实时计算压力。
52 0
|
6月前
模块功能复用和扩展性
模块功能复用和扩展性 模块功能复用和扩展性是软件工程中的重要概念,主要体现在设计和实现阶段。
86 1
|
设计模式 算法
如何优雅地使用策略模式来实现更灵活、可扩展和易于维护的代码?
如何优雅地使用策略模式来实现更灵活、可扩展和易于维护的代码?
88 0
|
测试技术 微服务
如何提高代码的扩展性(2)
如何提高代码的扩展性(2)
170 0
如何提高代码的扩展性(2)