最近在工作上像克拉克請益學習了許多Design Pattern,也開始著手將克拉克建議的架構要引入
iOS與Android的開發。在把這些架構帶入iOS與Android之前,第一篇就來個IOC
架構的研究,接著再一步步把這些架構引入跨平台開發。
IOC(Inversion of Control)的字面翻譯是反轉控制,用來去除物件與外部物件的相依性。
….再講甚麼亂七八糟的東西…沒關係,
這一篇就用三國無雙遊戲來解釋這個範例好了,這樣可能比較好懂 .
想像一下,我們要開發一個三國無雙的遊戲,
我們新建一個主控台應用程式,就想像這個主控台應用程式是PS3的搖桿。
接著想像你在玩三國無雙的時候,你的搖桿操縱著武將,他們之間的相依性可以用下圖來表示。
在專案中,我先建立一個類別,類別名稱叫做關羽。
在主控台程式中,撰寫底下的程式,建立關羽類別的實例,然後呼叫他的方法。
再提醒一下,這個主控台程式就是那隻PS搖桿喔!!
編譯程式可以看到底下的畫面程式呼叫了關羽類別。
但是當我們要在新增一個趙雲類別,問題開始產生了…
趙雲跟關羽一樣有小攻擊或者是無雙攻擊,在主要的主控台程式當中,
我們如果要判斷現在用的武將是那一個,這直接影響到畫面的呈現,
你到底用那一個武將,你按下無雙大絕招攻擊的時候,是呼叫那個武將類別來放大絕招?
程式就會變成下方這個樣子
多加了一個趙雲,就必須在Main類別中多加這麼多程式碼,如果再加入張飛,劉備….所有三國無雙的武將的話,
那這個程式可能就沒完沒了……
所以接下來我們稍作修正,去除掉物件依賴關係,把搖桿物件(主控台程式)與
武將類別的相依性去除掉。
新增一個Human的抽象類別,你可以想像三國無雙的武將們都是繼承這個抽象類別,
然後我在這個抽象類別中宣告了方法,所有武將都是繼承這個抽象類別,
最後再去複寫抽象方法。這樣每個人的無雙大絕招的內容也就會不一樣。
繼承抽象類別後,各個類別再去實作方法內容,
接著就是生成物件,在克拉克極簡風格的依賴注入模組 (DI Framework)一文中提到
一般業界常見的DI Framework,可以被分類為兩大種類:讀取DLL生成物件、讀取Config生成物件。
在這系列的範例我是以Factory的方式來生成與注入物件,除了這種方式我比較習慣外,
相對Xamarin.android 與 Xamarin.ios來說,使用Factory的方式來生成物件會比
使用讀取Config來生成物件來得稍微單純。其實就看你個人比較習慣那種用法了,榔頭鐵鎚用的順手最重要。
所以我建立了一個工廠類別,可以用來想像,其實前端要使用到武將類別,只要告訴我你要用誰,
就像三國無雙一開始在選單上選你要使用的武將一樣,這個工廠類別就出貨給你。
回到主控台程式,修改程式如下,當我們要使用那一個角色的,我們只要對工廠類別下訂單,
接著工廠類別會給我們相對應的武將,接下來我們就可以使用這個物件了,這樣程式碼變簡潔許多。
iOS與Android的開發。在把這些架構帶入iOS與Android之前,第一篇就來個IOC
架構的研究,接著再一步步把這些架構引入跨平台開發。
IOC(Inversion of Control)的字面翻譯是反轉控制,用來去除物件與外部物件的相依性。
….再講甚麼亂七八糟的東西…沒關係,
這一篇就用三國無雙遊戲來解釋這個範例好了,這樣可能比較好懂 .
想像一下,我們要開發一個三國無雙的遊戲,
我們新建一個主控台應用程式,就想像這個主控台應用程式是PS3的搖桿。
接著想像你在玩三國無雙的時候,你的搖桿操縱著武將,他們之間的相依性可以用下圖來表示。
在專案中,我先建立一個類別,類別名稱叫做關羽。
01 | //關羽類別 |
02 | public class GuanYu |
03 | { |
04 | //小攻擊 |
05 | public void hit() |
06 | { |
07 | Console.WriteLine( "關刀砍一下" ); |
08 | } |
09 | //無雙 |
10 |
11 | public void maxhit() |
12 | { |
13 | Console.WriteLine( "關刀砍阿..砍阿..砍阿..踹一腳..砍阿砍阿ㄚㄚㄚㄚㄚㄚ!!!!!!!!" ); |
14 | } |
15 | } |
再提醒一下,這個主控台程式就是那隻PS搖桿喔!!
01 | static void Main( string [] args) |
02 |
03 | { |
04 |
05 | GuanYu guanyu = new GuanYu(); |
06 | Console.WriteLine( "按下PS搖桿的○按鈕" ); |
07 | guanyu.hit(); |
08 | Console.WriteLine( "按下PS搖桿的□按鈕" ); |
09 | guanyu.maxhit(); |
10 |
11 | } |
但是當我們要在新增一個趙雲類別,問題開始產生了…
趙雲跟關羽一樣有小攻擊或者是無雙攻擊,在主要的主控台程式當中,
我們如果要判斷現在用的武將是那一個,這直接影響到畫面的呈現,
你到底用那一個武將,你按下無雙大絕招攻擊的時候,是呼叫那個武將類別來放大絕招?
程式就會變成下方這個樣子
01 | Console.WriteLine( "判斷目前使用的人物,選1是關羽,選2是趙雲。" ); |
02 |
03 | string player = Console.ReadLine(); |
04 | //選關羽的話 |
05 | if (player == "1" ) |
06 | { |
07 | GuanYu guanyu = new GuanYu(); |
08 | Console.WriteLine( "按下PS搖桿的○按鈕" ); |
09 | guanyu.hit(); |
10 | Console.WriteLine( "按下PS搖桿的□按鈕" ); |
11 | guanyu.maxhit(); |
12 | } |
13 |
14 | else if (player == "2" ) |
15 | { |
16 | ZhaoYun zhaoyun = new ZhaoYun(); |
17 | Console.WriteLine( "按下PS搖桿的○按鈕" ); |
18 | zhaoyun.hit(); |
19 | Console.WriteLine( "按下PS搖桿的□按鈕" ); |
20 | zhaoyun.maxhit(); |
21 | } |
22 |
23 | Console.ReadLine(); |
多加了一個趙雲,就必須在Main類別中多加這麼多程式碼,如果再加入張飛,劉備….所有三國無雙的武將的話,
那這個程式可能就沒完沒了……
所以接下來我們稍作修正,去除掉物件依賴關係,把搖桿物件(主控台程式)與
武將類別的相依性去除掉。
新增一個Human的抽象類別,你可以想像三國無雙的武將們都是繼承這個抽象類別,
然後我在這個抽象類別中宣告了方法,所有武將都是繼承這個抽象類別,
最後再去複寫抽象方法。這樣每個人的無雙大絕招的內容也就會不一樣。
1 | //宣告人物的抽象類別 |
2 | public abstract class Human |
3 | { |
4 | //宣告小攻擊的抽象方法,必須要在繼承的類別中實作 |
5 | public abstract void hit(); |
6 | //宣告無雙的抽象方法,必須要在繼承的類別中實作 |
7 | public abstract void maxhit(); |
8 | } |
繼承抽象類別後,各個類別再去實作方法內容,
01 | //關羽類別 |
02 | public class GuanYu : Human |
03 |
04 | { |
05 | //小攻擊 |
06 | public override void hit() |
07 | { |
08 | Console.WriteLine( "關刀砍一下" ); |
09 | } |
10 |
11 | //無雙 |
12 | public override void maxhit() |
13 | { |
14 | Console.WriteLine( "關刀砍阿..砍阿..砍阿..踹一腳..砍阿砍阿ㄚㄚㄚㄚㄚㄚ!!!!!!!!" ); |
15 | } |
16 |
17 | }<span style= "font-family: Arial, Verdana, sans-serif;" > </span> |
01 | //趙雲類別 |
02 | public class ZhaoYun : Human |
03 |
04 | { |
05 | //小攻擊 |
06 | public override void hit() |
07 |
08 | { |
09 | Console.WriteLine( "長槍~我戳" ); |
10 | } |
11 | //無雙 |
12 | public override void maxhit() |
13 | { |
14 | Console.WriteLine( "長槍戳阿..戳阿..戳阿..踹一腳..戳阿戳阿ㄚㄚㄚㄚㄚㄚ!!!!!!!!" ); |
15 | } |
16 |
17 | } |
01 | //張飛類別 |
02 | public class ZhangFei : Human |
03 | { |
04 | //小攻擊 |
05 | public override void hit() |
06 | { |
07 | Console.WriteLine( "蛇矛~我刺" ); |
08 | } |
09 | //無雙 |
10 | public override void maxhit() |
11 | { |
12 | Console.WriteLine( "蛇矛我刺..刺阿..刺阿..踹一腳..刺阿刺阿ㄚㄚㄚㄚㄚㄚ!!!!!!!!" ); |
13 | } |
14 | } |
一般業界常見的DI Framework,可以被分類為兩大種類:讀取DLL生成物件、讀取Config生成物件。
在這系列的範例我是以Factory的方式來生成與注入物件,除了這種方式我比較習慣外,
相對Xamarin.android 與 Xamarin.ios來說,使用Factory的方式來生成物件會比
使用讀取Config來生成物件來得稍微單純。其實就看你個人比較習慣那種用法了,榔頭鐵鎚用的順手最重要。
所以我建立了一個工廠類別,可以用來想像,其實前端要使用到武將類別,只要告訴我你要用誰,
就像三國無雙一開始在選單上選你要使用的武將一樣,這個工廠類別就出貨給你。
01 | static class HumanFactory |
02 |
03 | { |
04 | public static Human Getactor( string actor) |
05 | { |
06 | switch (actor) |
07 | { |
08 | case "1" : |
09 | return new GuanYu(); //回傳關羽物件 |
10 | case "2" : |
11 | return new ZhaoYun(); //回傳趙雲物件 |
12 | case "3" : |
13 | return new ZhangFei(); //回傳張飛物件 |
14 | default : |
15 | return null ; |
16 | } |
17 |
18 | } |
19 |
20 | } |
接著工廠類別會給我們相對應的武將,接下來我們就可以使用這個物件了,這樣程式碼變簡潔許多。
01 | Console.WriteLine( "判斷目前使用的人物,選1是關羽,選2是趙雲,3是張飛。" ); |
02 |
03 | string actor = Console.ReadLine(); |
04 |
05 | var actorobj = HumanFactory.Getactor(actor); |
06 |
07 | Console.WriteLine( "按下PS搖桿的○按鈕" ); |
08 |
09 | actorobj.hit(); |
10 |
11 | Console.WriteLine( "按下PS搖桿的□按鈕" ); |
12 |
13 | actorobj.maxhit(); |