• 设计模式---面向对象设计原则


    一:为什么提倡面向对象设计?

    变化时复用的天敌!
    面向对象设计的最大优势在于:抵御变化

    二:重新认识面向对象

    (一)理解隔离变化:

    从宏观层面来看,面向对象的构建方式更能适应软件的变化,能将变化所带来的影响减为最小(隔离不是绝对的)

    (二)各司其职

    从微观层面来看,面向对象的方式更强调各个类的”责任“。
    由于需求变化导致的新增类型不应该影响原来类型的实现。---是所谓的各负其责

    (三)对象是什么:

    从语言层面来看,对象封装了代码和数据。
    从规格层面讲,对象是一系列可被使用的公共接口。
    从概念层面讲,对象是某种拥有责任的抽象。

    三:设计模式基本原则

    最终目的:高内聚,低耦合

    (一)依赖倒置原则(DIP)

    高层模块(稳定)不应该依赖于低层模块(变化),二者都应该依赖于抽象(稳定)。
    抽象(稳定)不应该依赖于实现细节(变化),实现细节应该依赖于抽象(稳定)。

    传统过程设计:倾向于是高层次的模块依赖于低层次的模块,抽象层依赖于具体层(高度依赖)

    依赖倒置实现解耦合,将上面的依赖关系倒转过来

    (二)开放封闭原则(OCP)

    对扩展开放,对更改封闭
    类模块应该是可拓展的,但是不可修改
    类的改动是通过增加代码进行的,而不是修改源代码
    父类指针指向子类对象,使用多态等来扩展功能,某一个错误不会引起全局错误
    软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。

    原来的结构设计:将所有功能放在某一个大类中,导致业务扩展性差,修改都是在一个类模块中(易出现关联错误)

    符合开发封闭原则的设计:

    扩展方便

    (三)单一职责原则(SRP)

    类的职责要单一,对外只提供一种功能,而引起类变化的原因只有一个
    功能分开,各为一类。缺点:导致类太多
    一个类应该仅有一个引起它变化的原因。
    变化的方向隐含着类的责任
    如果一个类承担的职责过多,就等于把这些职责耦合在一起了。
    一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。
    这种耦合会导致脆弱的设计,当发生变化时,设计会遭受到意想不到的破坏。
    而如果想要避免这种现象的发生,就要尽可能的遵守单一职责原则。
    此原则的核心就是解耦和增强内聚性

    问题由来

    T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。也就是说职责P1和P2被耦合在了一起。

    解决方法

    职责扩散:因为某种原因,某一职责被分化为颗粒度更细的多个职责了
    
    遵守单一职责原则,将不同的职责封装到不同的类或模块中。

    优点

    1)降低类的复杂度;
    (2)提高类的可读性,提高系统的可维护性;
    (3)降低变更引起的风险(降低对其他功能的影响)

    (四)里氏替换原则(LSP)(多态)

    设计原则之里氏替换原则

    任何抽象类出现的地方,都可以用他的实现类进行替换(多态)。实际就是虚拟机制,语言级别实现面向对象功能
    子类必须能够替换它们的基类(IS-A)。
    继承表达类型抽象。

    原则:子类可以扩展父类的功能,但不能改变父类原有的功能。

    父类能出现的地方都可以用子类来代替,而且换成子类也不会出现任何错误或异常,而使用者也无需知道是父类还是子类,
    但反过来则不成立
         1. 子类必须完全实现父类的抽象方法,但不能覆盖父类的非抽象方法;
         2. 子类中可以增加自己特有的方法;
         3. 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数要更宽松;
         4.当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

    优点:

         1. 提高代码的重用性,子类拥有父类的方法和属性;
         2. 提高代码的可扩展性,子类可形似于父类,但异于父类,保留自我的特性;

    缺点:

         1. 继承是侵入性的,只要继承就必须拥有父类的所有方法和属性,在一定程度上约束了子类,降低了代码的灵活性;
         2. 增加了耦合,当父类的常量、变量或者方法被修改了,需要考虑子类的修改,所以一旦父类有了变动,很可能会造成
            非常糟糕的结果,要重构大量的代码。

    (五)接口隔离原则(ISP)

    接口隔离原则

    不应该强迫客户程序依赖它们不用的方法。
    接口应该小而完备。
    一个接口应该只提供一种对外功能,不应该把所有操作都封装到一个接口中去

    接口隔离原则和单一职责原则的区别

    接口隔离原则与单一职责原则的审视角度不相同。单一职责原则要求是类和接口的职责单一,注重的是职责,这是业务逻辑上的划分。
    接口隔离原则要求接口的方法尽量少。

    接口要尽量小

    这是接口隔离原则的核心定义,接口要尽量小,不要出现臃肿的接口,但是小也是有限度的,不能违背单一职责原则。

    接口要高内聚

    高内聚就是提高接口,类,模块的处理能力,减少对外的交互。具体到接口隔离原则就是要求在接口中尽量减少公布public方法,接口是对外的承诺,承诺越少对系统开发越有利,变更的风险就越少。

    原则

    一个接口只服务于一个子模块或业务逻辑
    通过业务逻辑压缩接口中的public方法,接口要不断的精简,以达到接口不断完善
    已经被污染的接口,尽量去修改,若变更的风险较大,则采用适配器进行转化处理

    (六)优先使用对象组合,而不是类继承

    理解组合对象与类继承

    类继承通常为“白箱复用”,对象组合通常为"黑箱复用"继承在某种程度上破坏了封装性,子类父类耦合度高。
    而对象组合则只要求被组合的对象具有良好定义的接口,耦合度低。
    如果使用了继承,会导致父类的任何变换都可能影响到子类的行为。
    如果使用对象组合,就降低了这种依赖关系
    对象组合要求被组合的对象具有良好定义的接口。

    (七)封装变化点

    使用封装来创建对象之间的分界层,让设计者可以在分界层的一侧进行修改,而不会对另一侧产生不良的影响,从而实现层次间的松耦合。
    例如:facade模式(外观模式)

    (八)迪米特法则:针对接口编程,而不是针对实现编程

    不将变量类型声明为某个特定的具体类,而是声明为某个接口。
    客户程序无需获知对象的具体类型,只需要知道对象所具有的接口。
    减少系统中各部分的依赖关系,从而实现”高内聚、松耦合“的类型设计方案。
    一个对象应该对其他对象尽可能少的了解,从而降低各个对象之间的耦合,提高系统的可维护性。
    例如在一个程序中,各个模块之间相互调用时,通常会提供一个统一的接口来实现,这样其他模块不需要了解另一个模块的内部实现细节,
    这样当一个模块内部的实现发生改变时,不会影响其他模块的使用(黑盒原理)

    四:面向接口设计

    产业强盛的标志就是接口便准化。

    五:将设计原则提升为设计经验

    设计习语 Design Idioms
    Design Idioms描述与特定编程语言相关的低层模式,技巧,惯用法。
    设计模式 Design Patterns
    Design Patterns主要描述的是”类与相互通信的对象之间的组织关系”,包括它们的角色、职责、协作方式等方面。
    架构模式 Architectural Patterns
    Architectural Patterns描述系统中与基本结构组织关系密切的高层模式,包括子系统划分,职责,以及如何组织它们之间关系的规则。
  • 相关阅读:
    美食小记
    美食小记
    移动端手势的七个事件库
    移动端手势的七个事件库
    利用PS把多张psd格式的图片转换为一张PDF格式
    利用PS把多张psd格式的图片转换为一张PDF格式
    常用的六个富文本编辑器
    常用的六个富文本编辑器
    如何获取公众号里面的歌曲
    快速幂算法
  • 原文地址:https://www.cnblogs.com/ssyfj/p/9522620.html
Copyright © 2020-2023  润新知