雙向分派模式-java版實現(xiàn)
原創(chuàng)?一個man?一個man?今天
先聊聊動態(tài)綁定和靜態(tài)綁定
動態(tài)綁定
動態(tài)綁定是指程序在運行期判斷引用的對象實際類型,根據(jù)實際的類型調(diào)用其相對應(yīng)的方法窍箍。
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...喵喵");}
}
靜態(tài)綁定
靜態(tài)綁定是在編譯期就已經(jīng)確認了執(zhí)行那個方法豪硅,方法重載(方法名相同參數(shù)列表不同)就是靜態(tài)綁定香璃,重載時執(zhí)行哪一個方法在編譯期就已經(jīng)確定了。
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");
? }
}
不管傳入的對象實際是什么類型都會執(zhí)行print(Person p)這個方法舟误,所以重載是靜態(tài)綁定葡秒。
如果希望使用重載的時候,程序能夠根據(jù)傳入?yún)?shù)的實際類型動態(tài)地調(diào)用相應(yīng)的方法嵌溢,只能通過instanceof操作符進行類型的判斷眯牧,然后再進行調(diào)用。雖然可以解決問題赖草,但是如果子類數(shù)目很多学少,那么就要寫很過個if else來判斷類型,顯然不是這種解決方案不是很合適秧骑。
雙分派
分派( dispatch)是指運行環(huán)境按照對象的實際類型為其綁定對應(yīng)方法體的過程版确。
double dispatch(雙分派)在選擇一個方法的時候,不僅僅要根據(jù)消息接收者(receiver) 的運行時型別(Run time type)乎折,還要根據(jù)參數(shù)的運行時型別(Run time type)绒疗。這里的消息接收者其實就是方法的調(diào)用者。具體來講就是骂澄,對于消息表達式a.m(b)吓蘑,雙分派能夠按照a和b的實際類型為其綁定對應(yīng)方法體。
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,在面向?qū)ο蟮乃枷胂铝彰ǎ绦蜃兊酶拥睦谕卣埂?/p>
寫到最后
過程式代碼難以添加新的數(shù)據(jù)結(jié)構(gòu)伟叛,因為如果要添加新的數(shù)據(jù)結(jié)構(gòu)就必須要修改所有函數(shù);面向?qū)ο蟠a難以添加新的函數(shù)脐嫂,因為如果要添加新的函數(shù)就必須修改所有的類痪伦。
[代碼簡潔之道]??第六章-對象和數(shù)據(jù)結(jié)構(gòu)