软件构造Delegation
引出:子类可以继承父类的字段、属性和方法,使用“继承”可以较大程度地复用代码。在使用继承时,务必要确定代码中定义的“父类”和“子类”确实存在客观的“父子关系”,而不要去做“为了代码复用而使用继承”的事情,这是舍本逐末的做法,也是滥用继承的体现。滥用继承会破坏类之间客观存在的关系,也会模糊代码所体现的语义。
委派和继承都是为了提高代码的复用性,只是方式不同。
委派:一个对象请求另一个对象的功能,捕获一个操作并将其发送到另一个对象。
继承:利用extends来扩展一个基类。
(1)Association:关联关系,永久性的delegation。被delegation的对象保存在rep中,该对象的类型被永久的与此ADT绑定在了一起。示例代码:
interface Flyable {
public void fly();
}
interface Quackable {
public void quack();
}
class FlyWithWings implements Flyable{
@Override
public void fly() {
System.out.println("fly with wings");
}
}
class Quack implements Quackable{
@Override
public void quack() {
System.out.println("quack like duck");
}
}
interface Ducklike extends Flyable,Quackable{
}
public class Duck implements Ducklike {
//delegation
Flyable flyBehavior;
Quackable quackBehavior;
//设置delegation对象实例
public void setFlyBehavior(Flyable flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(Quackable quackBehavior) {
this.quackBehavior = quackBehavior;
}
//通过delegation实现具体行为
@Override
public void fly() {
this.flyBehavior.fly();
}
@Override
public void quack() {
this.quackBehavior.quack();
}
}
public class Client {
public static void main(String[] args) {
Flyable f = new FlyWithWings();
Quackable q = new Quack();
Duck d = new Duck();
d.setFlyBehavior(f);
d.setQuackBehavior(q);
d.fly();
d.quack();
}
}
(2)Dependency:依赖关系,临时性的delegation。把被delegation的对象以参数方式传入。只有在需要的时候才建立与被委派类的联系,而当方法结束的时候这种关系也就随之断开了。示例代码:
public interface Study {
int study(String content);
}
class StudyInClass implements Study{
@Override
public int study(String content) {
return 1;
}
}
class StudyByMooc implements Study{
@Override
public int study(String content) {
return 2;
}
}
class Student{
private String name;
private Map<String,Integer> scores = new HashMap<String, Integer>();
public Map<String, Integer> getScores() {
return scores;
}
//AF:name为学生名字,scores中的key为学科名字,value为学生成绩
//RI:学生成绩范围为[0,100]
public Student(String name) {
this.name = name;
}
public int getFinalScore() {
int total = 0;
for(String content:scores.keySet()) {
total += scores.get(content);
}
return total;
}
//建立临时性的delegation关系
public int study(String content,Study method) {
System.out.print(content + ":\t");
return method.study(content);
}
public void getScore(String content,Study method) {
int score = method.study(content);
scores.put(content, score);
}
public static void main(String[] args) {
Study inClass = new StudyInClass();
Study byMooc = new StudyByMooc();
Student Wu = new Student("wyf");
Wu.study("软件构造", inClass);
Wu.getScore("软件构造", inClass);
System.out.println(Wu.getScores().get("软件构造"));
Wu.study("计算机系统", byMooc);
Wu.getScore("计算机系统", byMooc);
System.out.println(Wu.getScores().get("计算机系统"));
System.out.println("总成绩:" + Wu.getFinalScore());
}
(3)Composition: 更强的association,但难以变化。也就是以下代码Association中的法二。
(4)Aggregation: 更弱的association,可动态变化。也就是以下代码Association中的法一。
//法一:在构造方法中传入参数绑定
Flyable f = new FlyWithWings();
Duck d = new Duck(f);
d.fly();
class Duck {
Flyable f; //这个必须由构造方法传入参数绑定
public Duck(Flyable f) { this.f = f; }
public void fly(){ f.fly(); }
}
//法二:在rep或构造方法中直接写死
Duck d = new Duck();
d.fly();
class Duck {
//这两种实现方式的效果是相同的
Flyable f = new FlyWithWings(); //写死在rep中
public Duck() { f = new FlyWithWings(); } //写死在构造方法中
public void fly(){ f.fly(); }
}
参考文献:https://blog.csdn.net/weixin_44940258