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()
}
转载请注明出处哟~
https://www.cnblogs.com/lichengguo