第九章面向复用的软件构造技术
复用的级别
Source code level: methods, statements, etc
Module level: class and interface //可在java中使用类继承或者类委托的方式
Library level: API – Java Library, .jar
Architecture level: framework 框架
代码复用的种类:白盒复用和黑盒复用(顾名思义)
System-level reuse: Framework
框架:一组具体类、抽象类、及其之间的连接关系
开发者根据framework的规约,填充自己的代码进去,形成完整系统
White-box and Black-Box Frameworks
Whitebox frameworks 白盒框架,通过代码层面的继承进行框架扩展
Blackbox frameworks 黑盒框架,通过实现特定接口/delegation进行框架扩展
设计可复用的类
Liskov替换原则
定义:如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型。
- 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法;
- 子类中可以增加自己特有的方法。
协变:从宽泛到具体 ,逆变:从具体到宽泛
在java中arrays是协变的:也就是可以实现如下的结构:
Number[] numbers = new Number[2];
numbers[0] = new Integer(10);
numbers[1] = new Double(3.14);
Integer[] myInts = {1,2,3,4};
Number[] myNumber = myInts;
myNumber[0] = 3.14; //run-time error!
在java中泛型不是协变的,下面的代码将会发生Compile error
List<Integer> myInts = new ArrayList<>();
myInts.add(1);
myInts.add(2);
List<Number> myNums = myInts;
原因是:如果泛型类型中的类型参数是无限制的,将被对象类型参数所替 换因此,生成的字节码只包含普通类、接口和方法
不过可以通过使用通配符?来实现想要的效果
List<Integer> myInts = new ArrayList<>();
myInts.add(1);
myInts.add(2);
List<? extends Number> myNums = myInts;
继承和委托
Composite Reuse Principle (CRP) 复合重用原则
类通过“组合”实现多态和复用(通过引入其他类的实例来实现功能)而不是通过基类或父类。
热知识:java的接口可以多继承(😢我不会是最后一个知道的吧)
“委托”发生在object层面(动态的),而“继承”发生在class层面(静态的)
委托
委托的种类:
- 使用
- 关联(组合/聚合)
委托的等级:
-
Dependency:临时性的delegation
感觉类似设计模式中的strategy模式
Flyable f = new FlyWithWings(); Quakable q = new Quack(); Duck d = new Duck(); d.fly(f);class Duck{ //no field to keep Flyable object void fly(Flyable f){ f.fly(); } } -
Association:永久性的delegation
一个类有另一个作为属性/实例变量,但彼此仍可分
Flyable f = new FlyWithWings(); Duck d = new Duck(f); Duck d2 = new Duck(); d.fly();class Duck { Flyable f = new CannotFly(); void Duck(Flyable f) { this.f = f; } void Duck() { f = new FlyWithWings(); } void fly() { f.fly(); } } -
Composition:更强的association,但难以变化
不同于一般的Association,这里变成了其一部分属性,并且彼此不可分,在内部创建。
Duck d = new Duck(); d.fly();class Duck { Flyable f = new FlyWithWings(); void fly() { f.fly(); } } -
Aggregation:更弱的association,可动态变化
对象存在于另一个对象之外,是在外部创建的,因此它作为参数传递给构造函数
Flyable f = new FlyWithWings(); Duck d = new Duck(f); d.fly(); d.setFlyBehavior(new CannotFly()); d.fly();class Duck { Flyable f; void Duck(Flyable f) { this.f = f; } void setFlyBehavior(f) { this.f = f; } void fly() { f.fly();} }
Designing system-level reusable API libraries and Frameworks
白盒框架通常对应的设计模式是Template模式,通常是你面对继承而来的进行overriden(我觉得android中的Activity就是这样)
黑盒框架通常对应的设计模式是Strategy模式,通常是框架需要你面向接口编程
浙公网安备 33010602011771号