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

一、软件复用性

在这里插入图片描述

软件复用分为两个方面:面向复用编程(开发出可复用的软件)和基于复用编程(利用已有的可复用软件搭建应用系统) ,从而降低成本和开发时间,实现标准化,并让系统更加可靠、稳定。
在这里插入图片描述

高复用性的软件应简单、可移植性和兼容性好、灵活、可扩展、通用和参数化、模块化、将变化限制在局部、稳定。要考虑复用的机会有多频繁、代码有多大。

二、可复用性的层次和形态

1.概念:
最主要的复用是在代码层面,但是软件构造过程中的任何实体都可能被复用(需求、设计、规约、数据、测试用例、文档)
2.两种分类:
白盒复用:源代码可见,可修改和扩展(灵活、定制化程度高、难度大)
黑盒复用:源代码不可见,不能修改(简单、清晰、适用性差)
3.模块层次的复用(接口/类)
复用类的两种途径:继承和委托(在这里主要介绍委托)
继承不能取消属性或方法,所以必须小心不要过度!
委托只是当一个对象依赖另一个对象来实现其功能的某些子集时(一个实体将某些东西传递给另一个实体)
例:Sorter 将功能委托给某个 Comparator
显式委托:将发送对象传递给接收对象
隐式委托:通过语言的成员查找规则

委托有三种方式,分别是:Use,Composition/aggregation,Association
use就是调用了某个方法,通常称作“uses_a”。在这种情况下,通常不会将其作为成员变量,而是方法的参数或者局部变量。
association是将其作为成员变量,通常称作“has_a”,两者有关联但不一定要是组成关系。
composition通常称作“owns_a”,两者具有组成关系。
4.库级复用(库:一组提供可重用功能的类和方法 (API))
在这里插入图片描述

框架:可重用的骨架代码,可以定制到应用程序中
在这里插入图片描述

5.系统层面复用:框架
应用框架是包含了接口、抽象类和具体类的可复用程序,使用时需要在其基础上补充所需要的设计元素。开发者根据framework的规约,填充自己的代码进去,形成完整系统。可以将framework看作是更大规模的API复用,除了提供可复用的API,还将这些模块之间的关系都确定下来,形成了整体应用的领域复用。开发者需要做的就是增加新代码、对抽象类进行具体化。
在这里插入图片描述
白盒框架,通过代码层面的继承进行框架扩展
黑盒框架,通过实现特定接口/delegation进行框架扩展

三、设计可复用的类

1.行为子类型和里氏代换原则(LSP)
子类型多态:客户端可用统一的方式处理不同类型的对象
在这里插入图片描述
里氏替换原则:
定义1:如果对一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1所定义的程序P中在o1全都替换成o2时,程序的行为不发生任何变化,那么T2为T1的子类。
定义2:所有引用父类的地方都必须能够透明地使用其子类对象。
里氏替换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。
优点:
代码共享,减少创建类的工作量,每个子类都拥有父类的所有属性和方法;
提高代码的可重用性;
提高代码的可扩张性;
提高产品或项目的开放性。
缺点:
继承是入侵性的,拥有父类的属性和方法;
降低代码的灵活性,必须拥有父类的属性和方法;
增强耦合性,父类属性或方法改变,需要考虑子类。

2.代码示例如下:

class Employee
{
    func calculateSalary(name: String){ }
}

//总监
class Director: Employee
{
    override func calculateSalary(name: String)
    {
        print("\(name)总监的工资是10000");
    }
}

//经理
class Manager: Employee
{
    override func calculateSalary(name: String)
    {
        print("\(name)经理的工资是1000");
    }
}

//普通员工
class Staff: Employee
{
    override func calculateSalary(name: String)
    {
        print("\(name)员工的工资是100");
    }
}

//调用
let director: Employee = Director();
director.calculateSalary("张三");  //打印:张三总监的工资是10000
let manager: Employee = Manager();
manager.calculateSalary("李四");  //打印:李四经理的工资是1000
let staff: Employee = Staff();
staff.calculateSalary("王五");  //打印:王五员工的工资是100

3.Java会确保以下规则:
子类型可以增加方法,但不可删
子类型需要实现抽象类型中的所有未实现方法
子类型中重写的方法必须有相同或子类型的返回值
子类型中重写的方法必须使用同样类型的参数
子类型中重写的方法不能抛出额外的异常

或者说:更强的不变量、更弱的前置条件和更强的后置条件

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值