天天看點

設計模式 - 工廠方法模式簡介PHP 代碼示例Golang 示例

簡介

模式定義

在工廠方法模式中,工廠父類負責定義建立産品對象的公共接口,而工廠子類則負責生成具體的産品對象。工廠方法模式讓類的執行個體化延遲到子類中。

模式特點

工廠方法模式包含四個角色:

  • Product:抽象産品
  • ConcreteProduct:具體産品
  • Factory:抽象工廠
  • ConcreteFactory:具體工廠
設計模式 - 工廠方法模式簡介PHP 代碼示例Golang 示例

優缺點

  • 克服了簡單工廠的缺點,符合開放封閉原則。添加新産品時隻需要添加具體的工廠類,而不需修改抽象工廠
  • 添加新對象時,需要同時增加對象類和工廠類
  • 用法複雜,抽象工廠在實作時可能需要使用反射技術
  • 符合開閉原則,增加産品時隻需要增加一個具體工廠類

執行個體化的類可能會新增類型時,通常使用工廠模式作為建立對象的标準方式。

PHP 代碼示例

<?php

abstract class AbstractButtonFactory
{
	abstract public function getInstance();
}

class CircleButtonFactory extends AbstractButtonFactory
{
	public function getInstance()
	{
		return new CircleButton();
	}
}

class RectButtonFactory extends AbstractButtonFactory
{
	public function getInstance()
	{
		return new RectButton();
	}
}

abstract class AbstractButton
{
	abstract public function click();
}

class CircleButton extends AbstractButton
{
	public function click()
	{
		echo "I'm circle button";
	}
}

class RectButton extends AbstractButton
{
	public function click()
	{
		echo "I'm rectangle button";
	}
}

$cbf = new CircleButtonFactory();
$circleButton = $cbf->getInstance();
$circleButton->click();
           

Golang 示例

package main

import "fmt"

type Spliter interface {
    Split()
}

// type SplitFactory struct {}
// func (sf *SplitFactory) CreateSplit() Spliter {
//     // 編譯時依賴,仍然是緊耦合,隻有接口才能運作時綁定,實作晚綁定
//     return new(TxtSplit)
// }

type SplitFactory interface {
    CreateSplit() Spliter
}

type TxtSplit struct {}
func (s *TxtSplit) Split() {
    fmt.Println("TxtSplit Split")
}
type TxtSplitFactory struct {}
func (tsf *TxtSplitFactory) CreateSplit() Spliter {
    return new(TxtSplit)
}

type BinSplit struct {}
func (s *BinSplit) Split() {
    fmt.Println("BinSplit Split")
}
type BinSplitFactory struct {}
func (tsf *BinSplitFactory) CreateSplit() Spliter {
    return new(BinSplit)
}

func main() {
    // 預設構造方法,緊耦合
    var s Spliter
    s = new(BinSplit)
    s.Split()
    
    // 通過工廠解耦,此時工廠裡有緊耦合
    // sf := &SplitFactory{}
    // s2 := sf.CreateSplit()
    // s2.Split()
    
    // 通過具體工廠解耦
    tsf := new(TxtSplitFactory)
    s3 := tsf.CreateSplit()
    s3.Split()
}
           

繼續閱讀