GOLANG工厂模式、简单工厂模式、抽象工厂模式、创建者模式
? ? ? 設計模式可以大大提高代碼復用性,使得程序的修改更加靈活。另外將各個功能模塊抽象解耦出來,在某個模塊需要更改時不至于會對整體代碼進行修改,解耦的好的話只簡單修改幾個地方即可以切換某個模塊在實現上的切換,這就提高了程序修改的靈活度,以便應對客戶各種各樣的需求。
? ? ? ?大話設計模式第一章就通過寫一個計算器(計算邏輯和前端顯示解耦)和曹操飲酒改詩(每修改或者增加一個字就需要全部重新刻錄,并且就的刻版只能作廢)例子說明了設計模式的重要性。同時展示了簡單工廠模式,簡單工廠模式整體的思路是在一個創建函數中,通過switch case語句分別創建不同的實例,但是這些實例都有一些共同的屬性,比如加減運算中,在創建一個加法類時,這個類有兩個數字和一個返回結果的函數,減法也差不多一樣只是返回函數不一樣而已。這樣我們就可以用簡單工廠方法來生成加法類、減法類、乘法類等等。GO的實例代碼如下:
//這個interface用來保存大致一樣的類 type API interface {Say(name string) string }//這個是工廠函數,返回一個interface func NewAPI(t int) API {if t == 1 {return &hiAPI{}} else if t == 2 {return &helloAPI{}}return nil }//這個是一個具體的類型,hi type hiAPI struct{} func (*hiAPI)Say(name string) string {return fmt.Sprintf("Hi, %s", name) } //這是一個具體的類型,hai type helloAPI struct { } func (*helloAPI)Say(name string) string {return fmt.Sprintf("Hello, %s", name) }客戶端代碼: func TestType1(t *testing.T) {api := NewAPI(1)s := api.Say("Tom")if s != "Hi, Tom" {t.Fatal("Type1 test failed")} }? ? ? ? 簡單工廠模式在增加一個新的類型時,除了要增加新的類和方法之外,還需要修改工廠函數,在工廠函數中添加case,這一點違背了對修改關閉這個原則(開放-封閉原則),所以需要工廠模式。
工廠模式:定義一個用于創建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。看一下代碼你就知道了
package factoryCreatetype Operator interface {SetA(int)SetB(int)Result() int }//定義一個用于創建對象的接口 //實際中是這個interface在各個函數中傳來傳去,當需要實例化一個類的時候,調用Create方法 //具體的加減函數中,使用這個interface的Create方法返回的Operator interface做各種加減 type OperatorFactory interface {Create() Operator }type OperatorBase struct {a, b int } //set A func (o *OperatorBase) SetA(a int) {o.a = a } //SetB func (o *OperatorBase) SetB(b int) {o.b = b }//這里還創建一個新的加法工廠類,這個依賴于下面的具體加法類 type PlusOperatorFactory struct { } //這個類實現了這個方法之后,不但可以讓這個類的實例賦值給OperatorFactory //還可以通過這個函數創建加法實際操作的實例-PlusOperator類型的實例 func (PlusOperatorFactory) Create() Operator {return &PlusOperator{OperatorBase: &OperatorBase{},} } //具體的加法類 type PlusOperator struct {*OperatorBase } func (o PlusOperator) Result() int {return o.a + o.b }//減法工廠類,依賴于下面的具體減法類 type MinusOperatorFactory struct{} func (MinusOperatorFactory) Create() Operator {return &MinusOperator{OperatorBase: &OperatorBase{},} } //具體的減法類 type MinusOperator struct {*OperatorBase } func (o MinusOperator) Result() int {return o.a - o.b }//**************************客戶端代碼: func compute(factory OperatorFactory, a, b int) int {op := factory.Create()op.SetA(a) //這里類似于虛函數調用實際的子類函數。。。op.SetB(b)return op.Result() }func TestOperator(t *testing.T) {var (factory OperatorFactory //類似于基類)factory = PlusOperatorFactory{} //類似于一個子類if compute(factory, 1, 2) != 3 {t.Error("error with factory method pattern")}factory = MinusOperatorFactory{} //另一個子類if compute(factory, 4, 2) != 2 {t.Fatal("error with factory method pattern")} }?工廠函數在增加一個新的類型的時候,像上面的例子里,只要增加一個新類型的工廠類,里面實現
Create() Operator方法,同時增加具體類型type MinusOperator struct { *OperatorBase} 就好了。這里的OperatorBase是一個技巧。沒有違背開放-封閉原則。我們注意在客戶端中computer函數中我們可以做到不管你是加法還是減法,我們都調用了名字“一樣”的函數,運算與類的產生已經有所解耦了。但是假如,上面的例子中,我們不僅僅要產生Operator方法,我們還要給第一個數上黃色,第二個數上綠色,如果我們在Operator中添加方法的話,顯然需要改動的地方就太多了,我們應該是添加一個新的interface,里面有setAColor(),setBColor()方法,在客戶端我們拿到這個新的interface,然后調用setAColor()比較可取。這個功能就需要用到抽象工廠模式了抽象工廠模式:提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
package abstractfactoryimport "fmt"type OrderMainDAO interface {SaveOrderMain() }type OrderDetailDAO interface {SaveOrderDetail() } //這是一個接口,這個接口會創建一系列相互依賴(RDBDAOFactory和XMLDAOFactory 依賴于 OrderMainDAO)、 // 或者相互相關(OrderMainDAO和OrderDetailDAO相關)的對象, //在客戶端中創建RDBDAOFactory和XMLDAOFactory時,并不需要指定這兩個類型 type DAOFactory interface {CreateOrderMainDAO() OrderMainDAOCreateOrderDetailDAO() OrderDetailDAO }type RDBMainDAO struct { } func (*RDBMainDAO) SaveOrderMain() {fmt.Print("rdb main save\n") }type RDBDetailDAO struct { } func (*RDBDetailDAO) SaveOrderDetail() {fmt.Sprint("rdb detail save\n") }type RDBDAOFactory struct { } func (*RDBDAOFactory) CreateOrderMainDAO() OrderMainDAO {return &RDBMainDAO{} } func (*RDBDAOFactory) CreateOrderDetailDAO() OrderDetailDAO {return &RDBDetailDAO{} }//**********************type XMLMainDAO struct { } func (*XMLMainDAO) SaveOrderMain() {fmt.Sprint("xml main save\n") }type XMLDetailDAO struct { } func (*XMLDetailDAO) SaveOrderDetail() {fmt.Print("xml datail save") }type XMLDAOFactory struct { } func (*XMLDAOFactory) CreateOrderMainDAO() OrderMainDAO {return &XMLMainDAO{} } func (*XMLDAOFactory) CreateOrderDetailDAO() OrderDetailDAO {return &XMLDetailDAO{} }?
客戶端代碼
func getMainAndDetail(factory DAOFactory) {factory.CreateOrderMainDAO().SaveOrderMain()factory.CreateOrderDetailDAO().SaveOrderDetail() }func TestRdbFactory(t *testing.T) {var factory DAOFactoryfactory = &RDBDAOFactory{}getMainAndDetail(factory) }func TestXmlFactory(t *testing.T) {var facotry DAOFactoryfacotry = &XMLDAOFactory{}getMainAndDetail(facotry) }這里如果我們要在添加新的操作,也就是在DAOFactory這個interface中添加新的操作,我們需要改的地方就比較多。我們可以用簡單工廠來封裝一下,然后在簡單工廠函數中用反射來自動判斷需要創建那種類型,這是比較高級的玩法,留作練習。
總結
以上是生活随笔為你收集整理的GOLANG工厂模式、简单工厂模式、抽象工厂模式、创建者模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机操作系统学习笔记----进程管理
- 下一篇: 网络错误编码