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

复用的级别

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的子类型。

  1. 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法;
  2. 子类中可以增加自己特有的方法。

协变:从宽泛到具体 ,逆变:从具体到宽泛

在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模式,通常是框架需要你面向接口编程

posted on 2021-07-07 19:26  pluschen2000  阅读(34)  评论(0)    收藏  举报