软件构造(4-5)

4.Construction for Understandability(面向可理解性的软件构造技术)

主要讲解了如何写出更加让人容易理解的代码

4.1 编码规范

4.1.1 命名

驼峰命名法:
包名,类名,接口名:大写开头
变量名:第一个单词小写
参数名:具有实际含义而不是一个单独的字母
常量名:全大写

4.1.2 通过空行和空格来规范格式

在这里插入图片描述
过长的单行使用回车来直接分割
在这里插入图片描述

4.1.3 文件组织结构

import包时,按照字典序排序
包的文件准则

  • (REP) The Reuse/Release Equivalency Principle复用/发布等价原则
    尽量不使得单个的一个类在一个包中
  • (CCP) The Common Closure Principle共同封闭原则
    一个包中的所有类针对同一种变化是封闭的
    一个包的变化将会影响包里所有的类,而不会影响到其他的包
    如果两个类紧密耦合在一起,即二者总是同时发生变化,那么它们就应属于同一个包
  • (CRP) The Common Reuse Principle共同复用原则
    一个包里的所有类应被一起复用
    如果复用了其中一个类,那么就应复用所有的类
    包的耦合准则
  • (ADP) The Acyclic Dependencies Principle无圈依赖原则
    不允许在包依赖图中出现任何圈/回路
    消除圈的两种方式:
    创建新包
    利用DIP<依赖倒置原则>和ISP<接口隔离原则>
    在这里插入图片描述
  • (SDP) The Stable Dependencies Principle稳定依赖原则
    包之间的依赖关系只能指向稳定的方向,被依赖者应更稳定于依赖者,稳定的包较难发生改变
  • (SAP) The Stable Abstraction Principle稳定抽象原则
    在稳定性与抽象度之间建立关联,一个包是稳定的,那么它就应该尽可能抽象,一个完全稳定的包中只应包含抽象类。不稳定的包应是具体的,以便于容易的进行修改。

SAP和SDP共同构成了包之间的“依赖倒置原则DIP”。SDP:依赖应指向稳定的方向,SAP: 稳定性隐含着抽象。因此,依赖应指向抽象的方向。

5.面向可复用设计的软件构造

5.1 可复用性的度量、形态与外部表现

源代码级别的复用、模块级别的复用:类/抽象类/接口、库级别的复用:API/包、系统级别的复用:框架

5.1.1 代码复用

基于复用编程:利用已有的可复用软件搭建应用系统。面向复用编程:开发出可复用的软件

5.1.2 复用的等级和形态

代码级别:方法等
模块级别:类和接口
库级别:API
系统级别:框架

  • 代码级别
    白盒复用:源代码可见,可修改和扩展。复制已有代码当正在开发的系统,进行修改。可定制化程度高,对其修改增加了软件的复杂度,且需要对其内部充分的了解。
    黑盒复用:源代码不可见,不能修改。只能通过API接口来使用,无法修改代码。简单,清晰,但适应性差。
  • 模块级别
    继承和接口
  • 库级别
    易学、方便使用
  • 系统级别
    框架:一组具体类、抽象类、及其之间的连接关系。开发者根据framework的规约,填充自己的代码进去,形成完整系统。将framework看作是更大规模的API复用,除了提供可复用的API,还将这些模块之间的关系都确定下来,形成了整体应用的领域复用
5.1.3 额外的复用
  • 类型可变
    泛型:适应不同的类型,且满足LSP(5-2)
  • 实现可变
    ADT可以通过多种实现方式。虽然有不同的表示(Rep)和抽象函数(AF)但是却有相同的前置条件、后置条件和不变性。从而可以适应不同的应用场景。
    表示不变性,虽然内部的实现可能会经常发生变化,但是客户端不受影响。(表示独立,信息隐藏)

5.2 面向复用的软件构造技术

  • 设计可复用的类
    继承与重写、重载、参数多态与泛型编程、行为子类型与Liskov替换原则(LSP) 、组合与委派
  • 设计可复用的库和框架
    例:Java Collections
5.2.1 设计可复用的类
  • 行为子类型与Liskov替换原则(LSP)
    子类型多态:客户端可用统一的方式处理不同类型的对象
    在这里插入图片描述子类型的行为:
    1.子类型可以增加方法,但不可删
    2.子类型需要实现抽象类型中的所有未实现方法
    3.子类型中重写的方法必须有相同或子类型的返回值或者符合的参数
    4.子类型中重写的方法不能抛出额外的异常
    对于不变量来说:
    相同或者是更强的不变量、相同或者更弱的前置条件、相同或者更强的后置条件

  • Covariance (协变)和Contravariance (逆变)
    协变:父类型到子类型,更具体的规约。返回值和异常的类型要么保持不变要么变得更加具体。
    逆变:父类型到子类型,更具体的规约。但是参数类型变得更加宽泛了。
    在有容器套用的情况下,首先要求容器必须子类和父类的关系,再比较容器内部所储存的类型若相同则是子类和父类的关系。
    在这里插入图片描述

  • 通配符和泛型
    泛型在编译的时候就已经确定了所代表的类型。
    ? 可以匹配任何类,不同于Object,Object是所有类的父类。因为通配符可以和任何类型匹配,所以在遇到有容器套用的情况下,默认和容器内部储存的类型相同。
    ?extend Xxxx 说明:?继承于Xxxx
    ?super Xxxx说明:?是Xxxx的父类
    Integer-Number-Object

  • 组合与委派
    委派:通过运行时动态绑定,实现对其他类中代码的动态复用。
    如果一个类只需要使用父类很小一部分的代码,可以通过委托的方式进行复用而不是继承,避免了大量的无用的方法。

  • 接口的使用
    一个接口可以继承多个接口,然后这个接口再被其他的类来实现。

5.2.2 设计系统级别的库和框架

之所以library和framework被称为系统层面的复用,是因为它们不仅定义了1个可复用的接口/类,而是将某个完整系统中的所有可复用的接口/类都实现出来。并且定义了这些类之间的交互关系、调用关系,从而形成了系统整体的“架构”。

  • API设计
    API应该把一件事做得很好
    API应该尽可能的小
    API应该忽略具体实现
    考虑表现的后果
  • 框架设计
    (不太重要)
  • Java 集合框架(Collections)
    在这里插入图片描述
    Map的关系
    在这里插入图片描述
    Collections设计了如下的接口:
    size(), isEmpty(), contains(), add(), remove(), iterator(), toArray()
    Collections都不是线程安全的
    但是可以通过如下方式定义线程安全的集合
    Set s = Collections.synchronizedSet(newHashSet<>());

5.3 面向复用的设计模式

设计模式更多的强调的是多个类/对象之间的关系和交互过程。

  • 结构模式
    Adapter(适配器模式)Decorator(装饰器模式)Facade(外观模式)
  • 行为模式
    Strategy(策略模式)Template(模板模式)Iterator(迭代器模式)
5.3.1 适配器模式

将某个类/接口转换为client期望的其他形式。通过增加一个接口,将已存在的子类封装起来,client面向接口编程,从而隐藏了具体子类。
在这里插入图片描述

5.3.2 装饰器模式

用每个子类实现不同的特性,但是在对这个子类进行处理的时候,可能会出现多种共有的但是额外的特性。若果再单独建立子类的话会导致代码量特别巨大。所以
装饰器模式:对每一个特性构造子类,通过委派机制增加到对象上。
当客户端需要多种特性时,可以通过层层装饰来实现。

5.3.3 外观模式

客户端需要通过一个简化的接口来访问复杂系统内的功能,提供一个统一的接口来取代一系列小接口调用,相当于对复杂系统做了一个封装,简化客户端使用。可以理解成在外观模式定义的方法中,提供必要的参数然后将调用操作封装在其内部进行。
在这里插入图片描述

5.3.4 策略模式

有多种不同的算法来实现同一个任务,但需要client根据需要动态切换算法,而不是写死在代码里。
具体操作是,建立总策略接口,在里面声明方法,对于不同具体策略重写方法,达到不同策略的要求。

5.3.5 模板模式

做事情的步骤一样,但具体方法不同。共性的步骤在抽象类内公共实现,差异化的步骤在各个子类中实现 。
使用继承和重写实现模板模式,具体关系如图
在这里插入图片描述

5.3.6 迭代器模式

客户端希望遍历被放入容器/集合类的一组ADT对象,无需关心容器的具体类型 。也就是说,不管对象被放进哪里,都应该提供同样的遍历方式。
迭代器的三个需要重写的方法:hasNext, next, remove
并且需要在ADT中重写提供迭代对象的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值