软件构造复习内容(6)---可维护性

1.Modular design 模块化设计

  模块化编程想要实现的目标是

  • 高内聚        模块之内高内聚
  • 低耦合  模块之间低耦合

  https://blog.csdn.net/caoxuecheng001/article/details/80231220

  这个链接介绍了模块之间的耦合和聚合

  模块设计的5个原则

  Direct Mapping(直接映射)

  Few Interfaces(尽可能少的接口)

  Small Interfaces(尽可能小的接口)

  Explicit Interfaces(显式接口)

  Information Hiding(信息隐藏)

 

 

2.OO设计原则

  SOLID原则

  SRP(The Single Responsibility Principle) 单一责任原则

  OCP(The Open-Closed Principle) 开闭原则

  LSP(The Liskov Substitution Principle)  Liskov替换原则

  DIP(The Dependency Inversion Principle)  依赖-转置原则

  ISP(The Interface Segregation Principle)  接口聚合原则

  SRP:单一责任原则

    不应该有有多余一个原因让ADT变化,否则就拆开

    一个类,引起一个变化

    直观的理解就是一个类负责一个功能

  OCP:开闭原则

    对扩展性的开放,对修改的封闭

    模块的行为应该是可扩展的,从而满足新的需求

    但是模块自身的代码不应被修改,以保证原先功能的完好

    实现OCP的关键解决方法:抽象技术

    比如说要采用数据库,构造一个抽象的AbstractServer,然后具体的Server继承这个类,在使用时用AbstractServer声明数据库,然后进行使用

    对其的扩展很方便,新写一个使用其他数据库的类继承AbstractServer即可

  LSP:Liskov替换原则

    子类型必须能够替换其基类型

    派生类必须能够通过其基类的接口使用,客户端无需了解两者之间的差异。

    要求父类能实现的功能,子类也必须能够实现。

  ISP:接口隔离原则

    不能强迫客户端依赖于他们不需要的接口,只提供必须的接口

    不要胖接口不要胖接口不要胖接口

    胖接口不够聚合

    

    胖接口可以分解为多个小接口

    不同的接口向不同的客户端提供服务

    客户端只访问自己需要的接口

  DIP:依赖转置原则

    抽象的模块不应该依赖具体的模块

    具体应该依赖抽象

    上层的client的代码面向抽象接口编程,隔离对下层具体实现机制的直接接触

    即 delegation的时候要通过interface建立联系,而不是具体子类

 

3.OO设计模式

  1.Creational patterns (如何“创建新的实例”)

   (1)Factory method pattern 工厂模式

  当client不知道要创建那个具体类的实例时,或者不想在client代码中指明要具体创建的实例时,采用工厂方法

  定义一个用于创建对象的接口,让其子类来决定实例化哪一个类,从而使一个类的实例化延迟的其子类

  工厂内有一系列返回具体类的方法,客户端只需要调用工厂内的方法即可创建对象,当有新的具体产品类时,在工厂类中加入新的工厂函数(OCP,开闭原则)即可,不影响客户端代码

 

 

 

   静态工厂方法

    不需要创建工厂的实例,直接使用类名调用的工厂方法,既可以在ADT内部实现,也可以单独构造工厂类

  工厂方法很好的遵守了OCP原则

  (2)Abstract Factory 抽象工厂方法

    提供工厂模式,提供接口已创建一组相关/相互依赖的对象,但不需要指明具体类

    比如说,提供一组控件样式(2个按钮,1个文本框)就可以使用抽象工厂方法

 

 

 

 

  抽象工厂方法创建的不是一个完整的产品,而是产品族(遵循固定搭配规则的多类产品的实例),得到的结果是:多个不同的产品的Object,各产品创建过程对client可见,但是“搭配”不变

  2.Structural patterns(结构模式)

    (1)Proxy 代理模式

  某个对象比较“敏感”“私密”“贵重”,不希望被client直接访问到,故设置proxy,在二者之间建立防火墙

  client访问代理类,代理类委托真实类完成功能

  如果真实类实例化很复杂,可以减少消耗的时间,当真正用到相应的功能时,在委托真实类完成。

  3.Behavioral pattterns 表现模式

    (1)Observer 观察者模式 

    参考https://www.cnblogs.com/yssjun/p/11107038.html

      发布-订阅模式即多个订阅者(观察者)向发布者(被观察者)订阅状态信息,当发布者更新状态时会将状态信息向它的订阅者发布信息。发布者需要自己维护订阅者列表,可以注册或者注销对状态信息感兴趣或不感兴趣的订阅者。

      能够建立对象间一对多的关联关系,并且能使一个对象的变化被关联对象感知

    

 

   Subject:

    抽象被观察者(发布方),提供注册(Attach)和删除(Detach)观察者通知观察者的方法

  ConcreteSubject:

    具体被观察者,其中保存了所有需要被通知的观察者(有一个属性),并可以动态修改他的观察者(注册,删除),当其状态发生改变时,可以通知所有的观察者(Notify)

  

 

 

   Observer:

    抽象观察者,其中的Update方法提供被观察者通知时callback调用的。(可以降低类之间的耦合,提高内聚)

  ConcreteObserver:

    具体观察者,观察的对象是Subject(有一个属性),能接受Subject变化时发出的通知并更新自身的状态

  

 

   Java中已经提供了Observer接口,直接实现改接口,即可形成一个观察者

  Java中也提供了Observable抽象类,直接派生子类就是被观察者

  (2)Visitor  访问者模式

    对特定类型的object的特定操作(visit),在运行时将二者动态绑定到一起,该操作可以灵活更改,无需更改被visit的类

  本质上是将数据和作用于数据上的某种/些特定操作分离开

  为ADT预留一个将来可扩展功能的"接入点",外部实现的功能代码可以在不改变ADT本身的情况下通过delegation接入ADT。

  ADT:

  

 

  

 

  Visitor:

  

 

  Visitor实现

  

 

  使用:

  

 

4.状态模式

   避免使用过多的if-else判断状态,同时也容易新增状态

  State

  为每一个状态设计一个类,这些类均实现了State这一公共接口,这个接口中包含了涉及状态改变的方法

  状态类的设计采用单例模式,即每一个状态只能有一个实例。

  Context

  在Context中有一个属性(State state;)来控制状态及其改变,类中涉及状态改变的方法委托给具体的状态类来做,也可以保证在某些状态类下一些操作禁止的要求。但是state类仍要回调Context来完成功能,(低耦合,高内聚)所以状态改变的方法需要把Context传入作为参数。

  也可以把状态改变的功能(最基本的功能)交给状态类来做,具体功能放在Context中完成,但是这样需要判断当前状态是否合适。

  State模式的缺点之一是有许多空方法,因为State接口中的方法不是每一个状态都要实现,有些方法在对应状态下是被禁止。这一点和LSP原则有冲突。

5.Memento Pattern 备忘录模式

  记住对象的历史状态,以便于“回滚”。

  

 

 

 

 

  Memeto类只记录一个历史状态,在Originator中一次保存也只返回一个Memeto,同时恢复历史状态也可以利用Memeto。

  Caretaker管理所有的历史状态,将回滚要求发给Caretaker,Caretaker返回对应的当时状态

  比如说Caretaker用List保存所有的历史状态,回滚要求是向上回滚一步,那么返回当前状态对应的上一个状态Memeto给Originator即可。

 

posted @ 2020-06-24 16:40  GuiQuQu  阅读(298)  评论(0)    收藏  举报