设计模式-工厂模式-GoLang模板

 工厂模式的定义:

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。 ——《设计模式之禅》

工厂模式分类:

  • 一、简单工厂模式
  • 二、工厂方法模式
  • 三、抽象工厂模式

工厂模式区别:

  • 简单工厂 : 使用一个工厂对象用来生产同一等级结构中的任意产品。(不支持拓展增加产品)
  • 工厂方法 : 使用多个工厂对象用来生产同一等级结构中对应的固定产品。(支持拓展增加产品)
  • 抽象工厂 : 使用多个工厂对象用来生产不同产品族的全部产品。(不支持拓展增加产品;支持增加产品族)

一、简单工厂模式

package main

import "fmt"

// https://juejin.cn/post/7095581880200167432 用Go语言实现23种设计模式 - 掘金 - juejin
// 参考链接1:https://so.csdn.net/so/search?q=%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F&t=blog&u=weixin_43887447

// 定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类
// 工厂模式中的每个工厂只能生产一种产品,而抽象工厂模式将某些相关、等级结构不同的产品组成了一个“产品族”,然后用一个工厂来统一生产
// 注解:工厂模式只能生产一种产品,而抽象工厂模式可以生产一类产品
// 通用代码

/*
参考链接2: https://blog.csdn.net/lady_killer9/article/details/119296452
代码逻辑如下:
							  SimpleFactory
						-------------------------
						|CreateProduct() Product|
						-------------------------
									|
									|
									V
						    	Product
							---------------
							|Method() void|
							---------------
							7				^
						   /				  \
					      /					   \
					Product001				  Product002
				---------------			    ---------------
				|Method() void|				|Method() void|
				---------------				---------------

缺点:当添加一个新的Product003时,需要修改SimpleFactory里面的CreateProduct方法

*/

// 抽象的产品类---接口
type Product interface {
	Method() // 抽象方法
}

// 具体产品类001
type Product001 struct{}

// 具体产品类001实现接口的方法
func (p *Product001) Method() {
	fmt.Println("我是产品001")
}

// 具体产品类002
type Product002 struct{}

// 具体产品类002实现接口的方法
func (p *Product002) Method() {
	fmt.Println("我是产品002")
}

// 现在有一个工厂类,负责生产各种产品
type SimpleFactory struct{}

// 工厂生产各种产品的方法
func (s *SimpleFactory) CreateProduct(t string) Product {
	switch t {
	case "001":
		return &Product001{}
	case "002":
		return &Product002{}
	default:
		// 异常处理
		return nil
	}
}

// 测试简单工厂的方法
func TestSimpleFactory() {
	var fm = &SimpleFactory{}        // 开了一家工厂
	var p1 = fm.CreateProduct("001") // 制造产品001
	p1.Method()                      // 调用产品001的方法
	var p2 = fm.CreateProduct("002") // 制造产品002
	p2.Method()                      // 调用产品002的方法
}



// 在主函数中测试
func main() {
	TestSimpleFactory()
}

二、工厂方法模式

package main

import "fmt"

// 参考链接:https://blog.csdn.net/lady_killer9/article/details/119296452
// 工厂方法 : 使用多个工厂对象用来生产同一等级结构中对应的固定产品。(支持拓展增加产品)
// 1. 为了解决第一种简单工厂模式的缺陷,产生了工厂方法模式,把工厂方法再次进行抽象
// 2. 为不同的实现类,提供不同的工厂,通过实现抽象工厂接口类的方法,实现不同工厂获取
// 3. 业务实现类的不同实例,调用的时候,通过判断,使用不同的工厂(在简单工厂模式基础上)

/*
参考链接2: https://blog.csdn.net/lady_killer9/article/details/119296452
代码逻辑如下:
						    		Foods
							-----------------------
							|     Make()   void   |
							-----------------------
							7				       ^
						   /				        \
					      /					         \
					Vegetable				  		Meat
				---------------			    	---------------
				| Make()  void|					| Make()  void|
				---------------					---------------
					^								         ^
					.										 .
					.	          FoodsFactory			     .
					.		-------------------------		 .
					.		|    GetFood() Foods    |		 .
					.		-------------------------		 .
					.		7				         ^		 .
					.	   /				          \		 .
					.     /					           \	 .
				 VegetableFactory			        MeatFactory
				-----------------			    -----------------
				|GetFood() Foods|				|GetFood() Foods|
				-----------------				-----------------

优点:添加食物时,添加一个类和对应的具体工厂方法即可,不需要修改源代码
缺点:在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加;
	  在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
*/

// 抽象的 食物类  接口
type Foods interface {
	Make()
}

// 具体的 蔬菜类
type Vegetable struct{}

// 蔬菜类 实现食物类的Make方法
func (v *Vegetable) Make() {
	fmt.Println("我可以制作蔬菜类食物.")
}

// 具体的 肉类
type Meat struct{}

// 肉类 实现食物类的Make方法
func (m *Meat) Make() {
	fmt.Println("我可以制作肉类食物.")
}

// 不再提供一个统一的工厂类来创建所有的产品对象,而是针对不同的产品提供不同的工厂
// 故而需要一个抽象的工厂类,定义GetFood方法
type FoodsFactory interface {
	GetFood()
}

// 因为上面写了2种具体的食物类,所以需要实现2个具体的工厂类

// 1. 蔬菜类制作工厂
type VegetableFactory struct{}

// 2. 实现抽象工厂的 GetFood方法
func (vf *VegetableFactory) GetFood() Foods {
	return &Vegetable{}
}

// 3. 肉类制作工厂
type MeatFactory struct{}

// 4. 实现抽象工厂的 GetFood方法
func (mf *MeatFactory) GetFood() Foods {
	return &Meat{}
}

func TestFactoryMethod() {
	fmt.Println("测试工厂方法模式:")
	var vf = &VegetableFactory{} // 开了一家制作蔬菜的工厂
	var vege = vf.GetFood()      // 从工厂中获取一个要制作的蔬菜食物对象
	vege.Make()                  // 调用Make方法,制作食物
	var mf = &MeatFactory{}      // 开了一家制作肉类的工厂
	var meat = mf.GetFood()      // 从工厂中获取一个要制作的肉类食物对象
	meat.Make()                  // 调用Make方法,制作食物
}

// 在主函数main中测试
func main(){
    TestFactoryMethod()
}

三、抽象工厂模式

源自菜鸟教程

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象

package main

// 使用多个工厂对象用来生产不同产品族的全部产品。(不支持拓展增加产品;支持增加产品族)

/*
参考链接:https://blog.csdn.net/lvyibin890/article/details/107659348

场景描述:
现在有一个超级工厂,它负责创建实现了抽象工厂接口的工厂;
抽象工厂接口一共有三个方法,分别对应创建了三个产品族,分别是手机产品族,Ipad产品族与智能音箱产品族;
一共有两个工厂实现了这个抽象工厂接口,分别是华为工厂和小米工厂, 其中华为工厂不生产智能音箱产品族;

优点: 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点: 产品族扩展十分困难,当需要增加一个产品族的时候,抽象工厂需要多提供一个接口创建此产品族的产品,而具体的工厂也需要增加方法实现该接口
*/

import "fmt"

// 先定义几种工厂的类型
const (
	Huawei = iota
	Xiaomi
	Unsupported
)

// -----------------------------------------------------如下为三个产品族 手机、Ipad以及智能音箱-----------------------------------------------------
// 手机接口
type Cellphone interface {
	Call()
}

// Ipad接口
type Ipad interface {
	Play()
}

// 智能音箱接口
type SmartSoundBox interface {
	Listen()
}

// -----------------------------------------------------如下为抽象工厂接口,需要能够生产 手机、Ipad 以及 智能音箱-----------------------------------------------------
type AbstractFactory interface {
	CreateCellphone() Cellphone
	CreateIpad() Ipad
	CreateSmartSoundBox() SmartSoundBox
}

// -----------------------------------------------------如下为两个具体工厂 华为工厂和小米工厂-----------------------------------------------------
// 华为工厂:1. 实现 产品族的接口  手机接口 和 Ipad接口
type HuaweiCellphone struct{}

func (*HuaweiCellphone) Call() {
	fmt.Println("I made a call on my HuaweiCellphone")
}

// 华为Ipad
type HuaweiIpad struct{}

func (*HuaweiIpad) Play() {
	fmt.Println("I am playing with HuaweiIpad")
}

// 华为工厂:2. 实现了抽象工厂的两个接口

type HuaweiFactory struct{}

func (*HuaweiFactory) CreateCellphone() Cellphone {
	return &HuaweiCellphone{}
}

func (*HuaweiFactory) CreateIpad() Ipad {
	return &HuaweiIpad{}
}

// 华为工厂不生产智能音箱
func (*HuaweiFactory) CreateSmartSoundBox() SmartSoundBox {
	fmt.Println("Huawei not produce SmartSoundBox")
	return nil
}

// 小米工厂:1. 实现 产品族的接口  手机接口 、 Ipad接口 和智能音箱接口
type XiaomiCellphone struct{} // 小米手机,实现了手机接口

func (*XiaomiCellphone) Call() {
	fmt.Println("I made a call on my XiaomiCellphone")
}

// 小米Ipad
type XiaomiIpad struct{}

func (*XiaomiIpad) Play() {
	fmt.Println("I am playing with XiaomiIpad")
}

// 小米智能音箱
type XiaomiSmartSoundBox struct{}

func (*XiaomiSmartSoundBox) Listen() {
	fmt.Println("I am listening with XiaomiSmartSoundBox")
}

// 小米工厂:2. 实现了抽象工厂的两个接口
type XiaomiFactory struct{}

func (*XiaomiFactory) CreateCellphone() Cellphone {
	return &XiaomiCellphone{}
}

func (*XiaomiFactory) CreateIpad() Ipad {
	return &XiaomiIpad{}
}

func (*XiaomiFactory) CreateSmartSoundBox() SmartSoundBox {
	return &XiaomiSmartSoundBox{}
}

// -----------------------------------------------------如下为超级工厂接口,创建一个具体的 抽象工厂-----------------------------------------------------
type HyperFactory interface {
	CreateFactory(t int) AbstractFactory
}

// 超级工厂实例
type HypeFactoryImpl struct{}

// 根据给定的类型参数创建 对应的抽象工厂
func (*HypeFactoryImpl) CreateFactory(t int) AbstractFactory {
	switch t {
	case Huawei:
		fmt.Println("-----Creat Huawei Factory-----")
		return &HuaweiFactory{}
	case Xiaomi:
		fmt.Println("-----Creat Xiaomi Factory-----")
		return &XiaomiFactory{}
	default:
		return nil
	}
}

func TestAbstractFactory() {
	// 创建一个超级工厂,用于生产工厂
	var hf HyperFactory = &HypeFactoryImpl{}

	// 创建具体的工厂
	var factory AbstractFactory

	// 1. 具体的华为工厂
	factory = hf.CreateFactory(Huawei)
	factory.CreateCellphone().Call()
	factory.CreateIpad().Play()
	factory.CreateSmartSoundBox()

	// 2. 具体的小米工厂
	factory = hf.CreateFactory(Xiaomi)
	factory.CreateCellphone().Call()
	factory.CreateIpad().Play()
	factory.CreateSmartSoundBox().Listen()
}

func main(){
    TestAbstractFactory()
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值