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