【菜鸟日记】软件构造笔记5.2(详细版)

5.2.1 设计可复用的类

设计可复用的类的方法

  1. 继承和重写(3.4中有讲过)

多态和重载

(a)多态的概念:多态性是指为不同类型的实体提供一个接口,或者使用一个符号来表示多个不同的类型。多态性分为子类型多态性、参数多态性、特殊多态性、LSP(李氏替代原则)和行为子类型多态性
(b)常见的多态的例子:一个函数可以有多个同名的实现(方法重载);一个类型名字可以代表多个类型(泛型编程);一个变量名字可以代表多个类的实例(子类型)
(c)重载的规则:1)子类型可以添加方法,但不能删除方法;2)concrete类中必须实现所有未定义的方法;3)重写方法必须返回相同的类型或者子类型;4)重写方法参数类型必须和之前的相同。如:重写equal(Object o) 不能修改Object,修改后只能算重载,不算重写。5)重写可能不会引起其他的异常。
(d)LSP:相同或者更强的不变量;所有方法相同或者更强的后置条件;所有方法相同或者更弱的前置条件

-1-相同的不变量;更弱的前置条件;更强的后置条件
(e)型变:型变是指当子类型关系出现在更加复杂类型中时,如何处理新类型中的子类型关系。即输入输出类型可能会发生改变。型变分为协变、逆变和不变。

-2-图中T'是T的子类。图一是不变,AB中method方法参数和返回值完全相同;图二是协变,B是A的子类,B的返回值T‘也是A的子类;图三是协变,A的参数是B的子类,但A是B的父类,这里发生了反转;图四没有命名的类型
-3-getAnimalForAdoption是属于协变,但是putAnimal一般会识别为重载
(f)java中的泛型是不型变的:如 ArrayList 是 List的子类 – List 不是 List的子类。但是 List 是 List<? extends Animal>的子类, List 也是List<? super Cat>的子类。
(g)泛型:虚拟机中没有泛型类型对象,所有对象都属于普通类。泛 型信息只存在于编译阶段,在运行时会被”擦除” 。定义泛型类型时,会自动提 供一个对应的原始类型(非泛型类型),原始类型的名字就是去掉类型参数后的 泛型类型名。类型变量会被擦除,替换为限定类型,如果没 有限定类型则为Object类型。

-4-除了类名的T都被换成了Object
这里的T指定了类型Comparable
(h)泛型查询类的类型只能用getclass不能用instanceof

-5-

为什么java的泛型编程不型变

-6-会引起一些错误
下面这张图更加直观

-7-

关于extends和super与list

-8-super用于add ;extends 用于get

-9-为什么extends不能add
-10-为什么super不能用于get,因为毫无意义
-11-关于extends的一幅关系图

委托

定义:委托是指一个对象依赖于另外一个对象的部分功能 ,委托可看做是在实体之间共享代码和数据的低层机制,有利于复用,直白地说就是隐式地借用另一个类的方法来实现本类的功能。例如:
-12-委托的例子

-13-委托的例子

对比委托和继承(以栈为例子)

-14-用继承实现的栈中,除了含有栈的三个基本操作外,还多了两个继承的add和remove,与栈实际的操作不符,不利于实现栈的功能。而用委托实现就不会多出这两个

关于委托的一个非常容易错的例子

这个咋看以为最后会打印A中的bar中的信息,其实不然,编译器会自动默认this是当前程序即B,所以调用的是B中的bar(),this的指代和常规思维不一样!!!!!
-18-委托易错实例

关联关系

当定义一个变量时,会产生关联关系。
-19-关联关系

依赖关系

当一个对象的实施需要借助其他对象的实施,例如
-20-依赖关系定义示意图

组合和聚合

两者的差别:组合成员生命周期相同,而聚合成员生命周期无直接联系。如:大学与院系间是组合(若大学不复存在,则院系的存在也毫无意义),院系与教师间是聚合(院系不在了,老师还可以进入别的学院继续教授知识)

聚合的常见例子:注意,聚合用空心的菱形来表示

-21-聚合的常见例子,聚合用空心菱形

组合的常见例子

当人去世后,心脏的生命周期也就结束了;当窗口关闭后,窗口上的菜单的生命周期也一样结束。

-22-组合的常见例子

对象之间的联系小结(其中聚合一般可以用关联关系替代)

-23-对象之间的联系小结

一个比较生动的图可以帮助理解

-24-关系实例

5.2.2设计系统级可复用框架和库

设计 API

设计API一定要一开始就设计好,一旦发布,难以修改,因为可能会给别人带来很大影响,造成信任度降低。

什么样的API是好的API?

  • 功能单一
  • 命名不太长,但是意思清晰
  • 适合分解和合并模块
  • 既要体积小,但必要的性能不能丢
关于API类的设计
  • 尽量使用委托和组合
  • 不要因为单纯的复用实现而 使用继承,继承违反了封装原则
关于API方法的设计
  • 模块能做到的,就尽量不要客户端去做,减少模板代码的使用。
  • 要么正常结束,产生期望结果;要么整体失败,不产生任何的结果。例如copy,不要有copy一部分的情况,这样客户端无法判断实现情况,会造成未知的影响。
  • 对所有可访问数据提供String形式的访问方法,避免客户端去解析
  • 用空集合或者0长度数组, 不要用null(这样可以区分是越界还是本来就是空集合或者长度为0的数组)。
  • 尽量使用父接口,这样API更加灵活,比如尽量用Collection ,而不是list

设计框架

有框架尽量使用框架
在junit中的应用
-25-框架的运用

Java Collections 框架

-26-java collection 框架

collection接口

-27-collection接口

Iterator

-28-iterator实现

set
  • 增加了无重复元素的要求
  • 强制equals和hashCode计算

兼容问题

  • 向上兼容:向上兼容/向前兼容(forward),站在旧版软件 的立场,基于旧方法编写的软件不经修改就能在新版环境中运行
  • 向下兼容: 向后兼容/向下兼容(downward),站在新版 本的立场讨论对过去版本的兼容性问题,新版软件中可以支持旧版中 的方法
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值