最后更新于2022年6月8日 14:31:48

按照《研磨设计模式》这本书上面的生产电脑的例子,1156针脚的CPU与主板组合;939的互相组合,不能跨针脚组合。

CPU和主板的接口与实现类

这个没什么区别,两种工厂都一样的:

CPU:

type CPUApi interface {
	Calc()
}

/**
*  IntelCPU
*  @Description:
 */
type IntelCPU struct {
	pins int
}
func NewIntelCPU(pins int) *IntelCPU {
	return &IntelCPU{pins: pins}
}
func (i IntelCPU) Calc() {
	fmt.Println("Intel CPU, pins=", i.pins)
}

/**
*  AMDCPU
*  @Description:
 */
type AMDCPU struct {
	pins int
}
func NewAMDCPU(pins int) *AMDCPU {
	return &AMDCPU{pins: pins}
}
func (a AMDCPU) Calc() {
	fmt.Println("AMDYES!!!, pins=", a.pins)
}

主板:

type MainboardApi interface {
	InsCPU()
}

/**
*  GAMainboard
*  @Description:
 */
type GAMainboard struct {
	cpuHoles int
}
func NewGAMainboard(cpuHoles int) *GAMainboard {
	return &GAMainboard{cpuHoles: cpuHoles}
}
func (G *GAMainboard) InsCPU() {
	fmt.Println("Now in GAMainboard, cpuHoles= ", G.cpuHoles)
}

/**
*  MSIMainboard
*  @Description:
 */
type MSIMainboard struct {
	cpuHoles int
}
func NewMSIMainboard(cpuHoles int) *MSIMainboard {
	return &MSIMainboard{cpuHoles: cpuHoles}
}
func (G *MSIMainboard) InsCPU() {
	fmt.Println("Now in MSIMainboard, cpuHoles= ", G.cpuHoles)
}

工厂方法

重点是工厂方法的实现,先把自己的观点放在前面:抽象工厂生产的是方案,简单工厂生产的是零件

简单工厂:

package simple_fac

/**
*  createCPUApi
*  @Description:
*  @param t
*  @return CPUApi
 */
func CreateCPUApi(t int) CPUApi {
	var cpu CPUApi
	if t == 1 {
		cpu = NewIntelCPU(1156)
	} else if t == 2 {
		cpu = NewAMDCPU(939)
	}
	return cpu;
}

/**
*  createMainboardApi
*  @Description:
*  @param t type of CPU
*  @return MainboardApi
 */
func CreateMainboardApi(t int) MainboardApi {
	var mainboard MainboardApi
	if t == 1 {
		mainboard = NewGAMainboard(1156)
	} else if t == 2 {
		mainboard = NewMSIMainboard(939)
	}
	return mainboard
}

可以看到工厂创建出来的是具体的主板CPU这两个器件儿;
对应的简单工厂的组装工程师:

package simple_fac

type ComputerEngineer struct {
	cpu CPUApi
	mainboard MainboardApi
}

func NewComputerEngineer() *ComputerEngineer {
	return &ComputerEngineer{}
}

func (ce *ComputerEngineer) MakeComputer(cpu int, mainboard int) {
	//1、准备好装机的配件
	ce.prepareHWs(cpu, mainboard)
	//2、组装机器
	//3、测试机器
	//4、交付客户
}

func (ce *ComputerEngineer) prepareHWs(cpu int, mainboard int) {
	ce.cpu = CreateCPUApi(cpu)
	ce.mainboard = CreateMainboardApi(mainboard)

	ce.cpu.Calc()
	ce.mainboard.InsCPU()
}

组装的函数是MakeComputer(),
主函数如下:

package main

import "newPlayground0526/internal/simple_fac"

/**
*  main
*  @Description: 简单工厂
 */
func main() {
	engineer := simple_fac.NewComputerEngineer()
	engineer.MakeComputer(2, 2)
}
engineer.MakeComputer(1, 2)

抽象工厂

package ab_fac

type AbstractFactory interface {
	createCPUApi() CPUApi
	createMainboardApi() MainboardApi
}

// Schema1
type Schema1 struct {}
func (s *Schema1) createCPUApi() CPUApi {
	return NewIntelCPU(1156)
}
func (s *Schema1) createMainboardApi() MainboardApi {
	return NewGAMainboard(1156)
}

// Schema2
type Schema2 struct {}
func (s *Schema2) createCPUApi() CPUApi {
	return NewIntelCPU(939)
}
func (s *Schema2) createMainboardApi() MainboardApi {
	return NewGAMainboard(939)
}

跟简单工厂比起来,抽象工程生产的不是器件,而是Schema1和Schema2两个方案,相当于给器件之间添加了逻辑关系,就不会出现错误匹配的情况了。
相应的装机工程师的类是:

package ab_fac

type ComputerEngineer struct {
	cpu CPUApi
	mainboard MainboardApi
}

func NewComputerEngineer() *ComputerEngineer {
	return &ComputerEngineer{}
}

func (ce *ComputerEngineer) MakeComputer(schema AbstractFactory) {
	//1、准备好装机的配件
	ce.prepareHWs(schema)
	//2、组装机器
	//3、测试机器
	//4、交付客户
}

func (ce *ComputerEngineer) prepareHWs(schema AbstractFactory) {
	ce.cpu = schema.createCPUApi()
	ce.mainboard = schema.createMainboardApi()

	ce.cpu.Calc()
	ce.mainboard.InsCPU()
}

以下是主函数,看的更明显:

package main

import (
	"newPlayground0526/internal/ab_fac"
)

/**
*  main
*  @Description: 简单工厂
 */
func main() {
	engineer := ab_fac.NewComputerEngineer()
	schema := new(ab_fac.Schema1)
	engineer.MakeComputer(schema)
}

可见只要给装机工程师提供方案即可,避免了器件错位的情况。

吐槽

《研磨设计模式》里面有句话说的挺对的:工厂方法模式或简单工厂模式关注的是单个产品对象的创建,人家针对的问题就不是这种需要进行逻辑匹配的情况。