4-2 面向复用的软件构造技术
1、设计可复用的类
1.1 行为子类型和LSP
子类型:
相比于父类型,要有相同或更强的ADT(前置条件变弱或后置条件变强、更强的不变量);
在java中表现为:子类型可以增加方法;子类型中重写的方法必须返回相同或子类型的返回值(协变);子类型中重写的方法必须接受相同类型的参数(逆变);子类型重写的方法不能抛出额外异常。
例子:
假如一个长方形类、一个正方形类,然后正方形类继承长方形类。长方形有一个方法setWidth:改变某条边的长度。这时正方形类就无法继承这个方法,因为会破坏规约。正方形类和长方形类不应该是继承,而应该是委托的关系。
LSP:
协变:
子类型中重写的方法的返回值是父类中方法返回值的子类,子类的异常也应该是父类异常的子类。这种同向的变化就叫协变。
协变还有一层含义就是子类型的实例可以被赋给父类型:
逆变:
子类型中重写的方法的参数是父类中方法参数的父类。这种逆向的变化就叫逆变。java中不支持逆变,当作重载处理(Overload)。
数组是协变的。泛型不协变,泛型只存在于编译阶段,之后会被擦除,例如:List和List是相同的,类型擦除后都是List。
泛型擦除:
对于泛型使用类型查询:
instance of一个泛型类会编译不通过,getclass可运行,但运行时类型被擦除,故Pair<String>和Pair<Employee>是相等的。
泛型不存在协变,故不可以将一个泛型类赋值给另一个泛型类,这里的List<a>与List<b>毫无关系,故不可以这样赋值:
要写泛型方法可使用通配符:
下限通配符、上限通配符, 有了通配符,泛型就有子类的概念了:
PECS:producer要用super,consumer要用extend。
1.2、委托、组合
如果一个类继承另一个类,很可能继承下来很多不可用的方法,需要重写这些方法为空。好的做法:委托。可以避免大量不需要的方法。
ADT的比较的两种实现:
1、实现一个比较器,然后将比较任务委托给这个比较器Comparator;
注意comparator中compare函数的逻辑:返回1的时候将两个对象互换,所以下面这个是升序:
2、这个ADT实现Comparable接口,在ADT中实现compareTo函数,这样就把比较封装在了ADT内部,而不用额外实现一个比较器类,但这不是委托。
显式委托:通过传入对象,然后调用这个对象的方法,比如说比较器:
隐式委托:类中声明一个成员变量,然后类的方法调用这个成员变量的方法:
B隐式委托A,就是指B中声明一个A类型的成员变量a,然后B中方法的实现都依托于这个a。例如lab2中:
组合:问题在于对象层面而不在于类的层面,一个类的不同对象可能有不同的行为。
比如说开发一个动物类ADT,行为有叫和飞,有十余种飞和叫的方式,好的实现:接口之间通过extends实现拓展,比如说鸭子会叫又会飞,就可以extends Flyable、Quackable接口,其中Flyable、Quackable接口又各有十余种实现:
然后鸭子类对fly、quack的实现可以委托给Flyable和Quackable两个接口:
客户端给一个对象分配它的行为方式,这样同样是duck类,就可以有不同的行为方式:
组合的总体形式:
委托的种类:
(1)依赖Dependency
这是临时性的委托,通过方法传参建立局部的联系,被委托的对象也不是这个类的成员变量:
(2)association
这是永久性的委托,一个类将要委托的对象作为自己的成员变量,其有两种形态,分别是composition和aggregation。
(3.1)组合composition
这是更强的association,但难以变化,就是初始化的时候对成员变量进行赋值,是死的,没办法变化。
(3.2)聚合aggregation
这是更弱的association,可以动态变化,即有专门的方法对其成员变量进行赋值。
2、系统层面的可复用——库和框架
库的复用:我们写的代码调用库;
框架的复用:我们写的代码填充框架,框架调用我们写的代码。
白盒框架:
框架中有一些未完成的方法、空白,子类通过继承和重写方法完成对框架的填充、子类有主方法但调用是由框架调用。例如模板模式就是白盒框架。客户端写main。一次只能进行一次扩展,开发者框架。
一个抽象类白盒框架:
黑盒框架:
看不到代码,框架只提供一系列接口,通过plugin实现接口来实现框架的填充,相当于是通过委托来实现,由框架调用。框架写main。一次可进行多次扩展,用户框架。
这个黑盒框架有一个成员变量作为接口,外部plugin实现接口:
两个框架的工作流程:
设计框架的指导原则:
1、确定该框架的领域;
2、找出通用的部分,在框架中实现;
3、可变的部分留给外部去实现;
4、接口——抽象类——具体类:由抽象到具体,通用的向上放。
使用库和框架的投资回报曲线:
Collections介绍:
主要就是有四个接口:list、set、map、queue,实战都接触了,不记了。
迭代器的删除是安全的,其他对集合的删除会造成索引的混乱。
迭代器在4-3有详细介绍。
4-2 面向复用的软件构造技术相关推荐
- 软件构造学习笔记(九)面向复用的软件构造技术
目录链接 Part I What is Software Reuse? Part II How to measure "reusability"? Part III Levels ...
- 软件构造(九) 面向复用的软件构造技术
1.什么是软件复用 软件重用是使用现有软件组件实现或更新软件系统的过程. 软件复用有两方面: 面向复用编程:开发出可复用的软件 基于复用编程:利用已有的可复用软件搭建应用系统 为什么复用: 降低成本和 ...
- 面向复用的软件构造技术知识点总结与思考
一.复用 1.复用种类: 白盒复用:源代码可见,复制已有代码到正在开发的系统,进行修改和扩展 黑盒复用:源代码不可见,不能修改,只能通过API接口来使用 1)源码级别复用 2)模块级别复用:类,接口 ...
- 2022哈工大软件构造课程总结与经验分享(复习指导)
一.软构1-3讲 1.软件构造的多维度视图和质量目标 2.软件测试与测试优先的编程 3.软件构造过程与配置管理 二.软构4-8讲 4.数据类型与类型检验 5.设计规约 6.抽象数据类型 (ADT) 7 ...
- 2021哈工大软件构造期末考点复习笔记
第一节 多维视图和质量目标 软件构造多维度视图 红色标注为重点(考试会考选择题) Moment 特定时刻的软件形态 Period 软件形态随时间的变化 AST (Abstract Syntax Tre ...
- 2021-06-29 Views and Quality Objectives of Software Construction 软件构造的多维度视图和质量目标
第一章:Views and Quality Objectives of Software Construction 软件构造的多维度视图和质量目标 目标 1.从三个维度看软件系统的构成 2.用什么样的 ...
- [HITSC]哈工大2020春软件构造Lab3实验报告
Github地址 1 实验目标概述 本次实验覆盖课程第 3.4.5 章的内容,目标是编写具有可复用性和可维护 性的软件,主要使用以下软件构造技术: 子类型.泛型.多态.重写.重载 继承.代理.组合 常 ...
- HIT 软件构造 lab3实验报告
2020年春季学期 计算机学院<软件构造>课程 Lab 3实验报告 姓名 赵旭东 学号 1180300223 班号 1803002 电子邮件 1264887178@qq.com 手机号码 ...
- 2022 - 软件构造复习
软件生命周期 一个软件产品或软件系统经历孕育.诞生.成长.成熟.衰亡等阶段,一般称为软件生存周期(软件生命周期). 根据软件所处的状态和特征,划分软件生存周期. 需求定义.软件设计.软件实现.软件维护 ...
最新文章
- 电脑cpu排名_可能是最详细的小白【笔记本电脑】选购攻略(附热门机型推荐)...
- BOOST_VMD_ASSERT_IS_LIST相关的测试程序
- Linux下Anaconda3安装及使用教程
- solr后台界面介绍——(十一)
- linux shell之paste合并文件和找到匹配的文件里面替换内容(find和-exec或xargs组合)
- android生命周期_Android开发 View的生命周期结合代码详解
- eigen 列向量转矩阵_快速入门矩阵运算——开源库Eigen
- Bootstrap3 按钮组插件
- Linux 启动文件、设置环境变量的位置
- mysql 遍历二叉树_数据结构-二叉树遍历
- SSCI写作--期刊检索和基本介绍
- C语言编程常用知识点概论——第一章基本数据类型、运算符
- 注册登录页面模板 农业集团 金星农业
- 谷歌浏览器翻译插件 划词翻译
- 印刷电路板丝网设计的十大技巧
- Livid : 在 26 岁时写给 18 岁的自己
- python爬取pexels网站图片
- 三种页面置换算法(详解)
- PHP socket 连接 Socket server
- 2019 让自己变的更加优秀(文末新年福利)