软件构造博客五------软件构造技术

白盒复用:源代码可见而且可修改和拓展。黑盒复用源代码不可见,不能修改

白盒框架:通过代码层面的继承进行框架拓展。黑盒框架:通过实现特定接口/delegation进行框架拓展。

LSP原则:

子类型多态:客户端可用统一的方式处理不同类型的对象。

例如:

Animal a = new Animal();
Animal c1 = new Cat();
Cat c2 = new Cat();

在可以使用a的场景都可以使用c1和c2代替而不会存在任何问题。如果对于类型T的对象x,q(x) 成立,那么对于类型T的子类型S的对象y,q(y) 也成立。

子类型可以增加方法,但不可删;子类型需要实现抽象类型 (接口、抽象类)中所有未实现的方法。子类型中重写的方法必须有相同或子类型的返回值或者符合co-variant的参数。子类型中重写的方法必须使用同样类型的参数或者符合contra-variant的参数(此种情况Java目前按照重载overload处理)。子类型中重写的方 法不能抛出额外的异常。

LSP是一种特殊的子类型关系的定义,叫做强行为子类强化。在编程语言中,LSP依赖于以下限制:前置条件不能强化;后置条件不能弱化;不变量要保持;子类型方法参数:逆变;子类型方法的返回值:协变;异常类型:协变。

协变:父类型到子类型越来越具体,返回值类型不变或者变得更具体,异常的类型也是。

反协变,逆变:从父类型到子类型越来越具体,参数类型的变化相反,要不变或者越来越抽象。

例如:Java中数组是协变的: 对T[]数组,可以保存类型T及其子类型的数据。

下面是重点:对于泛型来说,泛型是类型不变的。类型参数在编译后被丢弃,在运行时不可用。这种操作叫做类型擦除。

 虚拟机中没有泛型类型对象-所有对象都属于普通类。泛型信息只存在于编译阶段,在运行时会被擦除。定义泛型类型时,会自动提供一个对应的原始类型(非泛型类型),原始类型的名字就是去掉类型参数后的泛型类型名。擦除时类型变量会被擦除,替换为限定类型, 如果没有限定类型则替换为Object类型。

运行时类型查询只适用于原始类型!!

一个类型变量如果有多个限定(类或接口),则它是所有限定类型的子类型;如果多个限定中有类(至多只允许一个类),要写到声明的最前面。限定的类型参数允许调用限定类型中的方法。

Delegation:委派/委托:一个对象请求另一个对象的功能。委派是复用的一种常见形式。举例如下:

很多设计模式将继承和委托结合使用。 

如果子类只需要复用父类中的一小部分方法,可以不需要使用继承,而是通过委派机制来实现。一个类不需要继承另一个类的全部方法,通过委托机制调用部分方法,从而避免继承大量无用的方法。组合优先于继承,“委托” 发生在object层面,而“继承”发生在class层面。

delegation的类型:

Dependency(A use B)   Association(A has B)   Composition/Aggregation(A owns B)

Dependency:临时性的delegation:通过方法的参数或者在方法的局部中使用发生联系。

Association: 永久性的delegation

Composition: 更强的association,但难以变化

Aggregation: 更弱的association,可动态变化

maintainability:可维护性  extensibility:可拓展性  flexibility:灵活性  adaptability:可适应性

manageability:可管理性    supportability:支持性

模块化编程:高内聚低耦合,分离关注点,信息隐藏

评估模块化的五个原则:可分解性,可组合性,可理解性,可持续性,出现异常之后的保护

可分解性:将问题分解为各个可独立解决的子问题。(目标:使模块之间的依赖关 系显式化和最小化。

可组合性:可容易的将模块组合起来形成新的系统。目标:使模块可在不同的环境下复用。

可理解性:每个子模块都可被系统设计者容易的理解。

可持续性:规格说明小的变化将只影响一小部分模块,而不会影响整个体系结构。模块提供的所有服务应该通过统一标识提供。

保护:运行时的不正常将局限于小范围模块内。

模块化设计的五个原则:Direct Mapping (直接映射);Few Interfaces (尽可能少的接口);Small Interfaces (尽可能小的接口) ; Explicit Interfaces (显式接口) ;Information Hiding (信息隐藏)。

直接映射:模块的结 构与现实世界中问题领域的结构保持一致;

少接口:模块应尽可能少的与其他模块通讯。对以下评价标准产生影响:可持续性、保护性、可理解性、可组合性。

小接口:如果两个模块通讯,那么它们应交换尽可能少的信息。

显式接口:当A与B通讯时,应明显的发 生在A与B的接口之间。

信息隐藏:经常可能发生变化的设计决策应 尽可能隐藏在抽象接口后面。

OO设计原则:SOLID(重点!)

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

ADT中不应该有多于1个原因让其发生变化,否则就拆分开。它是最简单的原则,却是最难做好的原则。

(2) Open/Closed Principle (OCP) (面向变化的)开放/封闭原则

对扩展性的开放:模块的行为应是可扩展的,从而该模块可表现出新的行为以满足需求的变化;

对修改的封闭:模块自身的代码是不应被修改的;扩展模块行为的一般途径是修改模块的内部实现。如果一个模块不能被修改,那么它通常被认为是具有固定的行为。

关键的解决方案:抽象技术

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

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

(4) Interface Segregation Principle (ISP) 接口隔离原则

不能强迫客户端依赖于它们 不需要的接口:只提供必需的接口。避免接口污染,避免“胖”接口。客户端不应依赖于它们不需要的方法;胖接口可分解为多个小的接口,不同的接口向不同的客户端提 供服务,客户端只访问自己所需要的端口。

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

高层模块不应该依赖于低层模块,二者都应该依赖于抽象。抽象不应该依赖于实现细节,实现细节应该依赖于抽象。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值