04-Go设计模式-抽象工厂方法模式

抽象工厂方法模式

代码
/*
抽象工厂方法模式

从工厂方法模式可以看出来:
(1)当添加一个新产品的时候,比如葡萄,虽然不用修改代码,但是需要添加大量的类,而且还需要添加相对的工厂。(系统开销,维护成本)
(2)如果使用同一地域的水果(日本苹果,日本香蕉,日本梨),那么需要分别创建具体的工厂,如果选择出现失误,将会造成混乱,虽然可以加一些约束,但是代码实现变得复杂。

所以“抽象工厂方法模式”引出了“产品族”和“产品等级结构”概念,其目的是为了更加高效的生产同一个产品组产品。
产品族:具有同一个地区、同一个厂商、同一个开发包、同一个组织模块等,但是具备不同特点或功能的产品集合,称之为是一个产品族
产品等级结构:具有相同特点或功能,但是来自不同的地区、不同的厂商、不同的开发包、不同的组织模块等的产品集合,称之为是一个产品等级结构
当程序中的对象可以被划分为产品族和产品等级结构之后,那么“抽象工厂方法模式”才可以被适用

抽象工厂模式的角色和职责
抽象工厂(Abstract Factory)角色:它声明了一组用于创建一族产品的方法,每一个方法对应一种产品
具体工厂(Concrete Factory)角色:它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中
抽象产品(Abstract Product)角色:它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法
具体产品(Concrete Product)角色:它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法

优点:
1. 拥有工厂方法模式的优点
2. 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
3  增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。

缺点:
1. 增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则”。
*/

package _2_abstract_factory

//============================= 抽象层 =======================================
type AbstractApple interface {
	ShowApple() string
}

type AbstractBanana interface {
	ShowBanana() string
}

type AbstractPear interface {
	ShowPear() string
}

//抽象工厂
type AbstractFactory interface {
	CreateApple() AbstractApple
	CreateBanana() AbstractBanana
	CreatePear() AbstractPear
}

//============================ 实现层 ======================================
/* 中国产品族 */
type ChinaApple struct {
}

func (ca *ChinaApple) ShowApple() string {
	return "中国苹果"
}

type ChinaBanana struct {
}

func (cb *ChinaBanana) ShowBanana() string {
	return "中国香蕉"
}

type ChinaPear struct {
}

func (cp *ChinaPear) ShowPear() string {
	return "中国梨子"
}

type ChinaFactory struct {
}

func NewChinaFactory() *ChinaFactory {
	return &ChinaFactory{}
}

func (cf *ChinaFactory) CreateApple() AbstractApple {
	return &ChinaApple{}
}

func (cf *ChinaFactory) CreateBanana() AbstractBanana {
	return &ChinaBanana{}
}

func (cf *ChinaFactory) CreatePear() AbstractPear {
	return &ChinaPear{}
}

/* 日本产品族 */
type JapanApple struct {
}

func (ja *JapanApple) ShowApple() string {
	return "日本苹果"
}

type JapanBanana struct {
}

func (jb *JapanBanana) ShowBanana() string {
	return "日本香蕉"
}

type JapanPear struct {
}

func (cp *JapanPear) ShowPear() string {
	return "日本梨子"
}

type JapanFactory struct{}

func (jf *JapanFactory) CreateApple() AbstractApple {
	return &JapanApple{}
}

func (jf *JapanFactory) CreateBanana() AbstractBanana {
	return &JapanBanana{}
}

func (cf *JapanFactory) CreatePear() AbstractPear {
	return &JapanPear{}
}

/* 美国产品族 */

测试代码
package _2_abstract_factory

import "testing"

func TestChina(t *testing.T) {
	if NewChinaFactory().CreateBanana().ShowBanana() != "中国香蕉" {
		t.Fatal("error")
	}

	if NewChinaFactory().CreateApple().ShowApple() != "中国苹果" {
		t.Fatal("error")
	}

	if NewChinaFactory().CreatePear().ShowPear() != "中国梨子" {
		t.Fatal("error")
	}
}

例子
package _2_abstract_factory

import "fmt"

//==================================== 抽象层 ==================================
type AbstractLogin interface {
	Login() string
}

type AbstractLogout interface {
	Logout() string
}

/*抽象工厂*/
type AbstractUserFactory interface {
	CreateLogin() AbstractLogin
	CreateLogout() AbstractLogout
}

//=================================== 实现层 ===================================
/* 支付宝产品族 */
type AlipayLogin struct {
	AlipayID       int
	AliPayPassword string
}

func (a *AlipayLogin) Login() string {
	fmt.Println("支付宝登录")
	return "支付宝登录"
}

type AlipayLogout struct {
}

func (a *AlipayLogout) Logout() string {
	fmt.Println("支付宝退出")
	return "支付宝退出"
}

type AlipayFactory struct {
}

func (a *AlipayFactory) CreateLogin() AbstractLogin {
	return &AlipayLogin{}
}

func (a *AlipayFactory) CreateLogout() AbstractLogout {
	return &AlipayLogout{}
}

//------------------------ 新加一个产品族很简单 符合开闭原则--------------------------------------
/* 微信产品族 */
type WechatLogin struct {
}

func (w *WechatLogin) Login() string {
	return "微信登录"
}

type WechatLogout struct {
}

func (w *WechatLogout) Logout() string {
	return "微信登录"
}

type WechatFactory struct {
}

func (w *WechatFactory) CreateLogin() AbstractLogin {
	return &WechatLogin{}
}

func (w *WechatFactory) CreateLogout() AbstractLogout {
	return &WechatLogout{}
}

//------------------------------- 新增加一个产品等级就很困难 ---------------------------------
//比如新增加一个获取token的产品等级,需要修改抽象层的代码,不符合开闭原则

package _2_abstract_factory

import (
	"testing"
)

func TestAlipay(t *testing.T) {
	ali := AlipayFactory{}
	ali.CreateLogin().Login()
	ali.CreateLogout().Logout()
}

//------------------------ 新加一个产品族很简单 --------------------------------------
func TestWechat(t *testing.T) {
	we := WechatFactory{}
	we.CreateLogin().Login()
	we.CreateLogout().Logout()
}

posted @ 2022-09-28 14:15  李成果  阅读(54)  评论(0编辑  收藏  举报