工厂模式主要有三种不同的实作:
这三种实作由简单到复杂,今天会介绍 Factory Method Pattern 延伸的 Abstract Factory Pattern
(文创系的看到我画的 UML 後画了一张他理解图,恩...真滴棒XD)
将性质相同产品集合起来由一个工厂生产
优点:
缺点:
我们修改昨天的情境,使用者想要有个「游戏房」,使用者除了要游戏主机,还要游戏产品。
套用到上方的 UML 图後如下:
我们的工厂 interface 不像昨天只是单纯生产游戏主机,而是要生产游戏屋相关的产品,所以改名为GameRoomFactory{}
,里头.GameMachineFactory()
可以生产主机,.GameFactory()
可以生产游戏。
而工厂生产的主机与游戏,也分别抽象出两个 interfaceGame
与GameMachine
。
使用者只管「把主机抱回家(.GameMachineFactory()
)」与「取得游戏来玩(.GameFactory()
)」,实际会获得什麽主机与游戏完全看使用者选择 Sony 还是任天堂。所以User()
会只依赖於GameRoomFactory{}
interface,并不直接呼叫SonyFactory{}
或NintendoFactory{}
。
选择品牌来决定要什麽样的产品集群,这样的集群又被称为「产品族」,在抽象工厂常用此名词称呼。
程序码如下:
(相关的 code 在Github - go-design-patterns)
package main
import "fmt"
// 定义抽象工厂
type GameRoomFactory interface {
GameMachineFactory() GameMachine
GameFactory() Game
}
// 定义抽象产品
type Game interface {
Start()
}
type GameMachine interface {
PlayGame()
}
// 实作产品
type PS5 struct{}
func (p PS5) PlayGame() {
fmt.Println("loading cd...play!")
}
func (p PS5) addCDMachine() {
fmt.Println("adding cd machine...done!")
}
func (p PS5) addCPU() {
fmt.Println("adding cpu...done!")
}
func (p PS5) addGPU() {
fmt.Println("adding gpu...done!")
}
type GameFinalFantasy struct{}
func (s *GameFinalFantasy) build() {
fmt.Println("build game...done!")
}
func (s *GameFinalFantasy) Start() {
fmt.Println("start game...done!")
}
type Switch struct{}
func (s Switch) PlayGame() {
fmt.Println("loading cd...play!")
}
func (s Switch) addCDMachine() {
fmt.Println("adding cd machine...done!")
}
func (s Switch) addCPU() {
fmt.Println("adding cpu...done!")
}
func (s Switch) addGPU() {
fmt.Println("adding gpu...done!")
}
type GameMario struct{}
func (s *GameMario) build() {
fmt.Println("build game...done!")
}
func (s *GameMario) Start() {
fmt.Println("start game...done!")
}
// 实作工厂
type SonyFactory struct{}
func (f *SonyFactory) GameMachineFactory() GameMachine {
ps5 := &PS5{}
ps5.addCDMachine()
ps5.addCPU()
ps5.addGPU()
return &PS5{}
}
func (f *SonyFactory) GameFactory() Game {
game := &GameFinalFantasy{}
game.build()
return game
}
type NintendoFactory struct{}
func (n *NintendoFactory) GameMachineFactory() GameMachine {
switchMachine := &Switch{}
switchMachine.addCDMachine()
switchMachine.addCPU()
switchMachine.addGPU()
return &PS5{}
}
func (n *NintendoFactory) GameFactory() Game {
game := &GameMario{}
game.build()
return game
}
func User(gameHomeFactory GameRoomFactory) {
gameMachine := gameHomeFactory.GameMachineFactory()
game := gameHomeFactory.GameFactory()
game.Start()
gameMachine.PlayGame()
}
func main() {
User(&SonyFactory{})
}
>>: [DAY 14] 轮回故事里的那些因果 : RNN 简介
Redis高可用性 前面的说明与范例都是透过单台的Redis Server的方式进行,这样的配置下当...
若您对於 Git 相当熟悉,你应该对於建立分支(Branch) 应该不陌生。依据 GitHub 官方...
今天要针对Routes和Middleware的部份进一步了解Express框架。 Express中的...
前情提要 前一篇文章带大家看了Requests-HTML 库的使用,用他来做资料清洗使我们真正想要的...
前言 路由简单来说就是连接介面的桥梁,而这个桥梁就叫做Navigator,就是导航的意思,用於管理进...