zoukankan      html  css  js  c++  java
  • 读书笔记---软件设计原则、设计模式

    这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/2021Softwarecodedevelopmenttechnology
    这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/2021Softwarecodedevelopmenttechnology/homework/11833
    这个作业的目标 学习并理解软件设计模式及其应该遵循的设计原则

    书籍:

        设计模式

    内容归纳:

     设计模式中的6个基本原则–SOLID

    SRP (单一职责)

    让接口设计最简(高内聚)做到只负责处理一类事件,类的设计尽量做到只因一个原因引起变化。
    好处:

      降低类的复杂性,明确实现的职责定义。

      提高可读性,便于维护。

      降低需求变更对整个项目的影响。

    OCP(开闭原则)

    开闭原则简而言之就是软件实体应该通过扩展来实现对需求变化的支持,而不是通过修改原有代码来实现变化。那么什么是软件实体呢?
    软件实体包括:

      抽象和类
      方法
      项目或软件中按照一定规则划分的模块
    好处:

      避免对原有代码的修改可以保证既有测试的正确性
      降低重构源码,对现有逻辑修改的风险
      提高代码的复用性,降低维护成本
      满足面向对象设计的需求

    LSP(里氏替换原则)

    里氏原则的定义:

      第一种定义:如果每个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有对象o1都换成o2时,程序P的行为没有发生变化,那么类型S就是T的子类型。
      第二种定义:只要父类能够出现的地方,必定可以使用子类来代替父类,并且不对程序产生任何影响。反之,能够出现子类的地方,就不一定能出现父类。<打个不恰当的比方 S 继承自 T ; T = new S(),但S    ~!= new T(); (“~!”简称“不一定等于”,o(∩_∩)o )>

      子类必须完全实现父类的方法。因为里氏替换原则规定只要父类能出现的地方就能出现子类。如果不完全实现父类的方法,那么通过子类实现父类的抽象方法后,父类调用定义的方法就会出现异常。

       复写(overload)或重写(override)父类方法时,子类方法的输入参数范围应该大于等于父类的参数范围,也就是说你在子类中写的这个方法是不会被调用的。因为在实际的应用中,父类一般都是抽象类,而子     类是实现类。如果子类的输入参数范围小于父类的参数范围,那么会导致子类复写方法被调用执行。这样的实现类会”歪曲“父类的意图,导致业务逻辑混乱。
       复写或重写父类方法时,子类方法的输出结果类型范围可以被缩小,意思就是父类返回一个T类型的返回值,那么子类可以返回一个S类型的返回值。(S可以是继承自T类型的子类或者和T是同一类型的)
    使用里氏原则设计的好处:

      增强程序的健壮性,版本升级也可以保持很好的兼容性
      代码共享,减少创建类的工作量,每个子类都有父类的方法和属性。
      提高代码的重用性。
      子类可以有自己的特性,但是在必要的时候又能当作父类来实现一些父类的方法。
      提高代码的可扩展性
      提高产品或项目的开放性

    LoD(迪米特法则)

    迪米特法则又称为最少知识原则,有点类似于领导让程序员实现功能一样,领导不需要知道怎么敲代码实现,只需要告诉程序员要什么,然后交给程序员来做出来就行了。 (有点类似于java中的封装,隐藏实现细节,只开放调用接口即可。)

    迪米特法则的目的:

           一个类尽量实现高内聚,减少public方法。

           减少程序之间的耦合度。

    ISP(接口隔离原则)

    接口隔离原则的定义有两种:

      接口尽量细化,别让一个接口太臃肿,接口中的方法尽量少。客户端中把不需要的接口干掉。
      类间的依赖关系,应该建立在最小接口上。这样的好处就在于,改变实现接口时,不会对现有逻辑造成干扰。
      接口隔离原则规范:

      接口要小,首先不要违背单一原则,保证一个事物的原子性(打个不恰当的比喻:不能因为要细化,而把人的 头、身体、分开,要保证这个人的头和身体属于一个接口类,这个就是最小)
      接口要高内聚,什么是高内聚?高内聚就是提高类、接口、模块的内部处理能力(比如一个接口定义了个人,人有姓名、性别、身高等。这个时候,接口可以在内部处理人的相关属性,提供一个public方法来      输 出这个人的所有属性。)<这一点符合迪米特法则>
      为特殊的需求定义单独的接口,避免不同的层级的方法出现在同一个接口中。
    衡量接口隔离的原则:
    接口隔离原则是对接口和类的定义。接口和类尽量使用原子接口和原子类来组装。在实践中,可以根据如下要求来衡量:

      一个接口只服务于一个模块或业务逻辑
      通过业务逻辑压缩接口中的public方法,实现接口的单一职责
      已经被污染的接口,尽量去修改。如果变更的风险较大,可以使用适配器模式进行转化处理。(适配器模式属于设计模式中的一种,后续博客会介绍)
    了解深层次的业务逻辑,根据不同的环境来拆分接口内容。
      比较极端的情况下,实现接口隔离原则,那就是一个接口一个方法,这个太浪费精力了。所以思考接口隔离原则需要考虑很多方面的因素,视情况而分。

    DIP(依赖倒置原则)

    依赖倒置的原始定义:

      高层模块不应该依赖底层模块,两者都应该依赖其抽象。
      抽象不应该依赖细节。
      细节应该依赖抽象。
      依赖倒置在Java中的体现

    模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象产生的。
    接口或抽象类不依赖于实现类。
    实现类依赖接口或抽象类。
    依赖倒置原则,说白了就是Java中面向接口编程的精髓。
    依赖倒置原则,可以减少类之间的耦合性,提高系统的稳定性,降低并行开发的风险,提高代码的可读性和可维护性。
    什么是依赖倒置?
    依赖倒置就是通过抽象(接口或抽象类)使各个类或模块的实现彼此独立,不互相影响,实现模块间的松耦合。比如在Java中定义一个人的接口IPerson,而Man实现了IPerson接口,那么可以直接使用IPerson = new Man();来实现一个男人的“依赖倒置”。在实现类中,只需要引用人这个抽象就可以在影响工程的情况下实现参数的变更。
    依赖倒置的原则

    每个类尽量都有接口或抽象类,或者抽象类和接口都具备。这是依赖倒置的基本要求,接口和抽象类都是抽象的,只有抽象了,才可能依赖倒置。
    变量表面类型近可是接口或者是抽象类
    如果基类一个方法是一个抽象类,并且这个方法已经在基类中实现,子类在继承基类时,尽量不要复写(Override)父类的这个方法。因为类间的依赖的是抽象,复写了抽象方法,对依赖的稳定性会产生一定的影响。
    任何类都不应该从具体类派生,这样会造成维护的麻烦,当然这个也不是绝对的。
    结合里氏替换原则使用依赖倒置。回顾一下,里氏要求 子类的引入参数范围比父类的范围要大或者相等。出现父类的地方子类都可以出现,这个结合依赖倒置的原则,可以发现,出现接口或抽象类的地方,其实现或子类都能出现。从而可以得出一个通俗的规则:
    接口负责定义public属性和方法,并声明与其他对象的依赖关系。
    抽象类负责公共构造部分的实现。
    实现类准确的实现业务逻辑,同时在适当的时候,将子类中公用的方法提升为父类中的公用方法,对父类进行细化

    体会

    在软件设计中,不可避免的要面对需求的变化。可以结合自身的需求来根据这六种简单的设计模式来设计出一个良好而稳定的架构,可以帮助我们少写很多冗余的代码。养成良好的编码习惯有助于技术的提升,当然作为程序员,务实是关键,多看大神写的代码,多实践。去其糟粕取其精华,才是王道。

  • 相关阅读:
    负载均衡算法实现方式
    TCP三次握手和四次挥手
    深度解析Java内存原型
    缓存击穿、缓存穿透和缓存雪崩
    uni-app分包加载
    vuex的使用
    在web中打开exe程序并传参
    Vue 中引用高德地图
    .Net Core 从MySql数据库生成实体类 Entity Model
    vs2017 创建项目推送到Git上
  • 原文地址:https://www.cnblogs.com/jmrlu/p/14551240.html
Copyright © 2011-2022 走看看