Unity應用架構設計 7 IoC工廠理念先行

2021-09-07 10:14:14 字數 3222 閱讀 2095

一談到『ioc』,有經驗的程式設計師馬上會聯想到控制反轉,將建立物件的責任反轉給工廠。ioc是依賴注入『di』的核心,大名鼎鼎的spring框架就是乙個非常卓越的的控制反轉、依賴注入框架。遺憾的是,我們顯然不能在unity 3d中去使用spring框架,但思想是相通的——ioc也好,控制反轉也罷,本質上是乙個工廠,或者又被稱為容器,我們可以自己維護乙個工廠來實現對物件的管理,這也是本文的核心內容。

工廠,顧名思義,就是生產物件的地方。如果之前沒有接觸過設計模式,你可能會疑惑,我直接使用『new』關鍵字難道不能建立物件嗎?為什麼還要大費周章的讓工廠來建立?當然這是沒錯的,直接使用『new』關鍵字很簡潔,也很易懂,但你考慮過物件的釋放嗎?你可能會說不用考慮啊,gc會幫我們**啊。

其實問題就出在這裡,因為你沒有考慮物件管理的動機,所以就不會有工廠這個概念。試想一下,使用ado.net或者jdbc去訪問資料庫,我們是不是要先建立乙個connection,當工作結束後,close了這個連線。當再一次需要連線資料庫時,再建立一次connection,這背後其實有隱患。因為和資料庫建立連線是非常耗時的,只是我們感受不到。我們能不能在關閉連線時,不銷毀物件,而是將其放到乙個物件池,當下一次請求來時,直接從物件池中獲取。這就是工廠的動機,對物件的建立和釋放進行管理,這樣可以有效的提高效率。

注:釋放指的是物件實現了idisposable介面的非託管資源,在umvvm框架,工廠維護的都是託管資源,銷毀由gc決定

在umvvm框架中,我將工廠分為三類:單例(singleton),臨時(transient),池(pool)。

我們可以為這三種工廠宣告公共的介面:iobjectfactory,這是非常有必要的,方便在執行時根據需求動態的切換不同工廠:

public inte***ce iobjectfactory

這個介面功能很簡單,通過統一的入口對物件進行建立與銷毀的管理。

有了統一的工廠的介面之後,接下來就是去實現對應的工廠了,第乙個要實現的就是 singleton factory:

public class singletonobjectfactory:iobjectfactory

return _cachedobjects;}}

}//...省略部分**...

public object acquireobject() where tinstance:class,new()

lock (_lock)}}

上述**中,我們需要定義乙個全域性的字典,用來儲存所有的單例,值得注意的是,cachedobjects 字典是乙個 static 型別,這表明這是乙個共享的字典,不會因為不同的singletonobjectfactory物件返回不唯一的例項物件。

還有一點,單例模式最好考慮一下多執行緒併發問題,雖然這是乙個『偽』需求,畢竟unity 3d是個單執行緒應用程式,但 umvvm 框架還是考慮了多執行緒併發的問題,使用 lock 關鍵字,它必須是乙個 static 型別,保證 lock 了同乙個物件。

transient factory 是最容易實現的工廠,不用考慮多執行緒併發問題,也不用考慮pool,對每一次請求返回乙個不同的物件:

public class transientobjectfactory : iobjectfactory

}

pool factory 相對來說是比較複雜的工廠,它對 transient factory 進行了公升級——建立例項前先去pool中看看是否有未被使用的物件,有的話,那麼直接取出返回,如果沒有則向pool中新增乙個。

pool的實現有兩種形式,一種是內建了諸多物件,還有一種是初始時是乙個空的池,然後再往裡面新增物件。第一種效率更高,直接從池裡面拿,而第二種更省記憶體空間,類似於懶載入,umvvm 的物件池技術使用第二種模式。

public class poolobjectfactory : iobjectfactory

public object obj

}private readonly list_pool;

private readonly int _max;

/// /// 如果超過了容器大小,是否限制

///

private readonly bool _limit;

public poolobjectfactory(int max, bool limit)

private pooldata getpooldata(object obj)}}

return null;

}/// /// 獲取物件池中的真正物件

///

///

///

private object getobject(type type)

", _pool[0].obj.gettype().name));}}

for (var i = 0; i < _pool.count; i++)

}if (_pool.count >= _max && _limit)

object obj = activator.createinstance(type, false);

var p1 = new pooldata

;_pool.add(p1);

return obj;}}

private void putobject(object obj)

}public object acquireobject(type type)

public void releaseobject(object obj)

var p = getpooldata(obj);

lock (_pool)

return;

}putobject(obj);}}

上述的**通過建構函式的 max 決定pool的大小,limit 引數表示超過pool容量時,是否可以再繼續往pool中新增資料。方法 getobject 是最核心的方法,邏輯非常簡單,獲取物件之前先判斷pool中是否有未被使用的物件,如果有,則返回,如果沒有,則根據 limit 引數再決定是否可以往pool中新增資料。

unity模組與架構設計0 簡介

模組可以理解為乙個黑盒子,我們輸入進入a可以得到b.而不用關心黑盒子裡怎麼把a變成b的 這樣,我們把程式封裝成乙個個模組,組裝起來,可以大大減少 的耦合性.還可以重複利用 我們的程式在開始寫之前,一定要有乙個統一的規範和結構,這個就是架構.沒有架構的程式,維護成本高,穩定性差.有一些經典的程式設計模...

Unity應用架構設計 13 日誌元件的實施

對於應用程式而言,日誌是非常重要的功能,通過日誌,我們可以跟蹤應用程式的資料狀態,記錄crash的日誌可以幫助我們分析應用程式崩潰的原因,我們甚至可以通過日誌來進行效能的監控。總之,日誌的好處很多,特別是對release之後的線上版本進行異常的跟蹤。而對於線上的版本,上述兩種除錯都不行,那我們怎麼來...

移動應用需要架構設計嗎

移動應用需要軟體架構設計嗎?這是個經常被提到的問題。回顧十幾年前為pc開發應用軟體的歷史。早期沒有架構設計,在可維護性和易擴充套件性上面都要付出相當大的成本。後來人們認識到了軟體架構的重要性,並使得軟體架構的概念逐漸成熟起來,在延長軟體的生命週期上發揮了巨大的作用。現在,幾乎所有的軟體都會經過架構設...