实用的设计模式-双分派模式
双向分派模式-java版实现
原创 一个man 一个man 今天
先聊聊动态绑定和静态绑定
动态绑定
动态绑定是指程序在运行期判断引用的对象实际类型,根据实际的类型调用其相对应的方法。
public class DynamicBinding {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
dog.talk();
cat.talk();
}
}
class Animal{
public void talk(){}
}
class Dog extends Animal{
public void talk(){System.out.println("dog talk...汪汪");}
}
class Cat extends Animal{
public void talk(){System.out.println("cat talk...喵喵");}
}
静态绑定
静态绑定是在编译期就已经确认了执行那个方法,方法重载(方法名相同参数列表不同)就是静态绑定,重载时执行哪一个方法在编译期就已经确定了。
public class DynamicBinding {
public static void main(String[] args) {
OutputName out = new OutputName();
Person p = new Person();
Person man = new Man();
Person woman = new Woman();
out.print(p);
out.print(man);
out.print(woman);
}
}
class Person {
}
class Man extends Person {
}
class Woman extends Person {
}
class OutputName {
void print(Person p) {
System.out.println("person");
}
void print(Man m) {
System.out.println("man");
}
void print(Woman w) {
System.out.println("woman");
}
}
不管传入的对象实际是什么类型都会执行print(Person p)这个方法,所以重载是静态绑定。
如果希望使用重载的时候,程序能够根据传入参数的实际类型动态地调用相应的方法,只能通过instanceof操作符进行类型的判断,然后再进行调用。虽然可以解决问题,但是如果子类数目很多,那么就要写很过个if else来判断类型,显然不是这种解决方案不是很合适。
双分派
分派( dispatch)是指运行环境按照对象的实际类型为其绑定对应方法体的过程。
double dispatch(双分派)在选择一个方法的时候,不仅仅要根据消息接收者(receiver) 的运行时型别(Run time type),还要根据参数的运行时型别(Run time type)。这里的消息接收者其实就是方法的调用者。具体来讲就是,对于消息表达式a.m(b),双分派能够按照a和b的实际类型为其绑定对应方法体。
public class DynamicBinding {
public static void main(String[] args) {
Father father = new Father();
Father s1 = new Son1();
Father s2 = new Son2();
Execute exe = new Execute();
father.accept(exe);
s1.accept(exe);
s2.accept(exe);
}
}
class Father {
public void accept(Execute exe) {
exe.method(this);
}
}
class Son1 extends Father {
@Override
public void accept(Execute exe) {
exe.method(this);
}
}
class Son2 extends Father {
@Override
public void accept(Execute exe) {
exe.method(this);
}
}
class Execute {
public void method(Father father) {
System.out.println("This is Father's method");
}
public void method(Son1 son) {
System.out.println("This is Son1's method");
}
public void method(Son2 son) {
System.out.println("This is Son2's method");
}
}
双分派模式下,无形中没有了繁琐的if。。else,在面向对象的思想下,程序变得更加的利于拓展。
写到最后
过程式代码难以添加新的数据结构,因为如果要添加新的数据结构就必须要修改所有函数;面向对象代码难以添加新的函数,因为如果要添加新的函数就必须修改所有的类。
[代码简洁之道] 第六章-对象和数据结构