第九章 面向复用的软件构造技术

一.软件复用
1.开发可复用软件;利用已有可复用软件
2.分析和提取相似的,降低成本和开发时间,测试比较充分,比较可靠,但是由于是更抽象的层面,针对性不强,所以性能较差
3.考虑的主要因素:适配性(因为一般情况下是针对普适场景)、成本
一般无法直接拿来就用,需要修改原来代码以适配对应具体对象
二.复用的级别和形态
1.代码层面
(1)层级:源代码:方法、陈述;模块:类、接口;库:API->java Library、.jar;结构:框架(大型程序)
2.代码复用的类型
(1)白盒复用:源代码可见,可修改和扩展(需要对源代码内部充分了解)->源代码;黑盒复用:源代码不可见,不能修改;只能通过接口来使用(适应性差)->jar,dll,gem…
3.源代码复用(复制粘贴)
4.类层面复用:类和接口
(1)继承:或者和父类一样,否则重写(子类方法一定要比父类多)
(2)委托:通过成员变量和方法调用产生相关关系->不是永久(当前类调用了其他某个类的方法时生效)
显式委托:把调用对象发给对方
隐式委托:成员变量的形式
5.API/Package层面
(1)类库(控制逻辑在程序员这里,程序员决定调用具体哪个类)
(2)Framework:一件事情的流程顺序,分几步…,每个步骤怎么做随意(控制逻辑在framework里面,framework作为主程序加以执行,执行过程中调用开发者所写的程序,程序员只能按照这个步骤来写)
6.Framework(见第5条)
(1)开发者根据framework的规约,填充自己的代码进去,形成完整系统
(2)白盒框架,通过代码层面的继承进行框架扩展
(3)黑盒框架,通过实现特定接口/delegation进行框架扩展
三.设计可复用的类
1.LSP
(1)子类型多态:客户端可用统一的方式处理不同类型的对象
在这里插入图片描述
(2)LSP:如果对于类T的对象x,q(x)成立,那么对于其子类型S的对象y,q(y)也成立
(3)子类型可以增加方法,但不可删;子类型需要实现抽象类型中的所有未实现方法;子类型中重写的方法必须有相同类型的返回值或者符合子类型的返回值;子类型中重写的方法必须使用同样类型的参数或者符合子类型的参数(目前按照重载处理);子类型中重写的方法不能抛出额外的异常,抛出相同或者符合子类型的异常
(4)更强的不变量,更弱的前置条件,更强的后置条件->(只有规约更强才能替换,无法比较或者规约更弱就无法替换);可见性只能更强不能更弱
在这里插入图片描述
后三个IDE能检查出来,前面三个IDE检查不出来
2.逆变和协变
(1)协变:父类型->子类型:越来越具体specific;返回值类型:不变或变得更具体;异常的类型:也是如此(一子类全子类)。
在这里插入图片描述
在这里插入图片描述
(2)逆变:父类型->子类型:越来越具体specific;参数类型:要相反的变化,要不变或越来越抽象
在这里插入图片描述
目前Java中遇到这种情况,当作overload看待
注意多态时会遇到一个问题,就是声明变量的类型与实际指向的类型不一致,本例中java知道Number数组被实例化为Integer数组,通过Number[]引用进行访问
在这里插入图片描述
3.泛型中的LSP
(1)泛型是类型不变的,不支持协变,例:
在这里插入图片描述
(2)泛型的类型参数是在编译时被丢弃,在运行时不可用(类型擦除)
在这里插入图片描述
泛型当中视为二者不是同一类型(两个类型无关),这样的赋值是不被允许的,编译就报错
泛型擦除:build time->run time
在这里插入图片描述
在这里插入图片描述
泛型要是extends后面接类的话就是继承某个类,后面接的是接口的话就是实现某个接口
运行时类型查询只适用于原始类型,instanceOf操作就不允许了,getClass允许但是不一定会得到想要的结果
在这里插入图片描述
可以采用通配符来实现两个泛型的协变
(1)?表示无限定通配符,适用于两种情况:方法的实现不依赖于类型参数(不调用其中方法),如List中方法;(2)只依赖于Object类中的功能
无限定通配符一般用于定义一个引用变量,可以指向多个不同类型的变量
(2)<?super A>是下限通配符,<? extends A>是上限通配符,extends可以代表继承类或实现接口
子类型可以赋给父类型,父类型不可以赋给子类型
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
四.委托和组合
1.Comparator接口,只有一个方法int compare(T o1, T o2),返回1,0,-1;需要比较大小时可以实现此接口并重写compare函数,例:
在这里插入图片描述
2.Comparable接口:本身也有个compareTo的方法,不需要构建新的Comparator类,实现是在ADT内部,不是委托
在这里插入图片描述
3.委托
(1)在两个类之间建立联系
A a = new A(); private A a; // delegation link
B b = new B(a); public B(A a) {this.a = a;}
(2)委派模式:通过运行时动态绑定,实现对其他类中代码的动态复用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
委托给graph来处理
在这里插入图片描述总结:委托通过创建被委托的类中的对象建立两个类之间的联系,通过这个对象调用被委托的类中的方法
“委托”发生在object层面,而“继承”发生在class层面
委托优先于继承(CRP)
可以设计多个接口,一个接口设计一个行为,具体类想实现哪个就实现哪个
例:
在这里插入图片描述
将飞和叫分别委托给Flyable,Quackable类来办,这里的f,q是具体的实例化对象
(3)委托的形式:依赖(A里面一个方法调用B里面另外一个方法);联系(有成员变量);组合和聚合(也是成员变量,联系的两种具体形态)
依赖通过方法的参数或在方法的局部使用发生关系
依赖:1.这里d和f通过参数传递产生关系,在方法调用完之后,两者就不再有关系
在这里插入图片描述
关联关系:通过成员变量产生依赖关系,是永久关系
在这里插入图片描述
duck里面有一个会飞的f,duck和fiyable之间建立永久关系;f可以在生成后就赋值(组合),也可以在构造函数或其他set方法中赋一个新的值(聚合)
组合:非常强的关联关系,这个例子中的d和f,但难以变化(duck已经确定好就和这个f关联)->生命周期一致
在这里插入图片描述
聚合:弱一些的关联关系,具体关联到的对象通过构造函数描述出来(duck会和某一个f进行关联,但是不知道具体是和哪个f关联)->生命周期分开
在这里插入图片描述
例:前者是聚合,后者是组合
在这里插入图片描述
四.API和framework层面的复用
1.白盒框架:继承机制,继承和重写->模板模式
2.黑盒框架:实现接口,委托机制->策略模式和观察者模式
3.黑盒控制权在framework,白盒控制权在用户

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值