之前我們介紹了工廠設計模式,現在我們再看一下抽象工廠設計模式。抽象工程模式顧名思義就是對工廠模式的一層抽象,也是建立型模式的一種,通常用來建立一組存在相關性的物件。

UML類圖大致如下:

類圖比較複雜,最好用個例子來說明。比方說,國內有兩家生產運動服的工廠:nike和adidas 。現在我們想購買一套運動服,包含短褲(short)和運動鞋(shoe)。通常我們都會在同一家工廠購買整套的運動服。這時抽象工廠模式就可以發揮作用了。

現在我們需要的產品有兩種:短褲(short)和運動鞋(shoe)。

生產這些產品的工廠有兩家:nike和adidas。

nike和adidas都是運動服廠商,可以視為是 iSportsFactory介面的實現

然後,我們還要為具體的產品定義兩個介面:

  • iShort,它有兩個實現,分別是nikeShortadidasShort
  • iShoe,它也有兩個實現,分別是nikeShoeadidasShoe

看下具體的程式碼:

iSportsFactory.go

package main

import "fmt"

type iSportsFactory interface {
makeShoe() iShoe
makeShort() iShort
} func getSportsFactory(brand string) (iSportsFactory, error) {
if brand == "adidas" {
return &adidas{}, nil
}
if brand == "nike" {
return &nike{}, nil
}
return nil, fmt.Errorf("Wrong brand type passed")
}

  iShort.go

package main

type iShort interface {
setLogo(logo string)
setSize(size int)
getLogo() string
getSize() int
} type short struct {
logo string
size int
} func (s *short) setLogo(logo string) {
s.logo = logo
} func (s *short) getLogo() string {
return s.logo
} func (s *short) setSize(size int) {
s.size = size
} func (s *short) getSize() int {
return s.size
}

  iShoe.go

package main

type iShoe interface {
setLogo(logo string)
setSize(size int)
getLogo() string
getSize() int
} type shoe struct {
logo string
size int
} func (s *shoe) setLogo(logo string) {
s.logo = logo
} func (s *shoe) getLogo() string {
return s.logo
} func (s *shoe) setSize(size int) {
s.size = size
} func (s *shoe) getSize() int {
return s.size
}

  nike.go

package main

type nike struct {
} type nikeShoe struct {
shoe
} type nikeShort struct {
short
} func (n *nike) makeShoe() iShoe {
return &nikeShoe{
shoe: shoe{
logo: "nike",
size: 14,
},
}
} func (n *nike) makeShort() iShort {
return &nikeShort{
short: short{
logo: "nike",
size: 14,
},
}
}

  adidas.go

package main

type adidas struct {
} type adidasShoe struct {
shoe
} type adidasShort struct {
short
} func (a *adidas) makeShoe() iShoe {
return &adidasShoe{
shoe: shoe{
logo: "adidas",
size: 14,
},
}
} func (a *adidas) makeShort() iShort {
return &adidasShort{
short: short{
logo: "adidas",
size: 14,
},
}
}

  main.go

package main

import "fmt"

func main() {
adidasFactory, _ := getSportsFactory("adidas")
nikeFactory, _ := getSportsFactory("nike")
nikeShoe := nikeFactory.makeShoe()
nikeShort := nikeFactory.makeShort()
adidasShoe := adidasFactory.makeShoe()
adidasShort := adidasFactory.makeShort()
printShoeDetails(nikeShoe)
printShortDetails(nikeShort)
printShoeDetails(adidasShoe)
printShortDetails(adidasShort)
} func printShoeDetails(s iShoe) {
fmt.Printf("Logo: %s", s.getLogo())
fmt.Println()
fmt.Printf("Size: %d", s.getSize())
fmt.Println()
} func printShortDetails(s iShort) {
fmt.Printf("Logo: %s", s.getLogo())
fmt.Println()
fmt.Printf("Size: %d", s.getSize())
fmt.Println()
}

 程式碼已上傳至GitHub:zhyea / go-patterns / abstract-factory-pattern

End!