天天看点

设计模式 - 工厂方法模式简介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()
}
           

继续阅读