java单分派与多分派(多路分发和单路分发)(二)

2014-11-24 11:42:04 · 作者: · 浏览: 14
nt((InputMethodEvent)e);
} else if (e instanceof HierarchyEvent) {
switch (e.getID()) {
case HierarchyEvent.HIERARCHY_CHANGED:
processHierarchyEvent((HierarchyEvent)e);
break;
case HierarchyEvent.ANCESTOR_MOVED:
case HierarchyEvent.ANCESTOR_RESIZED:
processHierarchyBoundsEvent((HierarchyEvent)e);
break;
}
}
}
这种方法实现的双重分派都格外的冗长、复杂和容易出错,也不符合“开闭原则”。
方案二:反转球
通过两次的调用来实现,比如下面剪刀石头布的游戏:
[java]
public enum Outcome { WIN, LOSE, DRAW } ///:~
interface Item {
Outcome compete(Item it);
Outcome eva l(Paper p);
Outcome eva l(Scissors s);
Outcome eva l(Rock r);
}
class Paper implements Item {
public Outcome compete(Item it) {
return it.eva l(this);
}
public Outcome eva l(Paper p) {
return DRAW;
}
public Outcome eva l(Scissors s) {
return WIN;
}
public Outcome eva l(Rock r) {
return LOSE;
}
public String toString() {
return "Paper";
}
}
class Scissors implements Item {
public Outcome compete(Item it) {
return it.eva l(this);
}
public Outcome eva l(Paper p) {
return LOSE;
}
public Outcome eva l(Scissors s) {
return DRAW;
}
public Outcome eva l(Rock r) {
return WIN;
}
public String toString() {
return "Scissors";
}
}
class Rock implements Item {
public Outcome compete(Item it) {
return it.eva l(this);
}
public Outcome eva l(Paper p) {
return WIN;
}
public Outcome eva l(Scissors s) {
return LOSE;
}
public Outcome eva l(Rock r) {
return DRAW;
}
public String toString() {
return "Rock";
}
}
public class RoShamBo1 {
static final int SIZE = 20;
private static Random rand = new Random(47);
public static Item newItem() {
switch (rand.nextInt(3)) {
default:
case 0:
return new Scissors();
case 1:
return new Paper();
case 2:
return new Rock();
}
}
public static void match(Item a, Item b) {
System.out.println(a + " vs. " + b + ": " + a.compete(b));
}
public static void main(String[] args) {
for (int i = 0; i < SIZE; i++)
match(newItem(), newItem());
}
}
RoshamBol.match()有2个item参数,通关过Item.compete()方法开始2路分发,要判定a的类型,分发机制会在a的实际类型的compete()内部起到分发作用。compete()方法通关过eva l()来为另一个类型实现第二次分发, 将自身(this)作为参数调用eva l(),能够调用重载过的eva l()方法,这能够保留第一次分发的类型信息,第二次分发完成时,就能知道两个Item对象的具体类型了。
这种实现也就是“访问者模式”的精华。