【golang设计模式】Golang设计模式详解二

六、工厂方法模式
工厂方法模式使用子类的方式延迟生成对象到子类中实现。
Go中不存在继承 所以使用匿名组合来实现
代码如下:
factorymethod.go

package factorymethod

//Operator 是被封装的实际类接口
type Operator interface {
    SetA(int)
    SetB(int)
    Result() int
}

//OperatorFactory 是工厂接口
type OperatorFactory interface {
    Create() Operator
}

//OperatorBase 是Operator 接口实现的基类,封装公用方法
type OperatorBase struct {
    a, b int
}

//SetA 设置 A
func (o *OperatorBase) SetA(a int) {
    o.a = a
}

//SetB 设置 B
func (o *OperatorBase) SetB(b int) {
    o.b = b
}

//PlusOperatorFactory 是 PlusOperator 的工厂类
type PlusOperatorFactory struct{}

func (PlusOperatorFactory) Create() Operator {
    return &PlusOperator{
        OperatorBase: &OperatorBase{},
    }
}

//PlusOperator Operator 的实际加法实现
type PlusOperator struct {
    *OperatorBase
}

//Result 获取结果
func (o PlusOperator) Result() int {
    return o.a + o.b
}

//MinusOperatorFactory 是 MinusOperator 的工厂类
type MinusOperatorFactory struct{}

func (MinusOperatorFactory) Create() Operator {
    return &MinusOperator{
        OperatorBase: &OperatorBase{},
    }
}

//MinusOperator Operator 的实际减法实现
type MinusOperator struct {
    *OperatorBase
}

//Result 获取结果
func (o MinusOperator) Result() int {
    return o.a - o.b
}

factorymethod_test.go

package factorymethod

import "testing"

func compute(factory OperatorFactory, a, b int) int {
    op := factory.Create()
    op.SetA(a)
    op.SetB(b)
    return op.Result()
}

func TestOperator(t *testing.T) {
    var (
        factory OperatorFactory
    )

    factory = PlusOperatorFactory{}
    if compute(factory, 1, 2) != 3 {
        t.Fatal("error with factory method pattern")
    }

    factory = MinusOperatorFactory{}
    if compute(factory, 4, 2) != 2 {
        t.Fatal("error with factory method pattern")
    }
}

七、抽象工厂模式
抽象工厂模式用于生成产品族的工厂,所生成的对象是有关联的。

如果抽象工厂退化成生成的对象无关联则成为工厂函数模式。

比如本例子中使用RDB和XML存储订单信息,抽象工厂分别能生成相关的主订单信息和订单详情信息。
如果业务逻辑中需要替换使用的时候只需要改动工厂函数相关的类就能替换使用不同的存储方式了。

代码如下:
abstractfactory.go

package abstractfactory

import "fmt"

//OrderMainDAO 为订单主记录
type OrderMainDAO interface {
    SaveOrderMain()
}

//OrderDetailDAO 为订单详情纪录
type OrderDetailDAO interface {
    SaveOrderDetail()
}

//DAOFactory DAO 抽象模式工厂接口
type DAOFactory interface {
    CreateOrderMainDAO() OrderMainDAO
    CreateOrderDetailDAO() OrderDetailDAO
}

//RDBMainDAP 为关系型数据库的OrderMainDAO实现
type RDBMainDAO struct{}

//SaveOrderMain ...
func (*RDBMainDAO) SaveOrderMain() {
    fmt.Print("rdb main save\n")
}

//RDBDetailDAO 为关系型数据库的OrderDetailDAO实现
type RDBDetailDAO struct{}

// SaveOrderDetail ...
func (*RDBDetailDAO) SaveOrderDetail() {
    fmt.Print("rdb detail save\n")
}

//RDBDAOFactory 是RDB 抽象工厂实现
type RDBDAOFactory struct{}

func (*RDBDAOFactory) CreateOrderMainDAO() OrderMainDAO {
    return &RDBMainDAO{}
}

func (*RDBDAOFactory) CreateOrderDetailDAO() OrderDetailDAO {
    return &RDBDetailDAO{}
}

//XMLMainDAO XML存储
type XMLMainDAO struct{}

//SaveOrderMain ...
func (*XMLMainDAO) SaveOrderMain() {
    fmt.Print("xml main save\n")
}

//XMLDetailDAO XML存储
type XMLDetailDAO struct{}

// SaveOrderDetail ...
func (*XMLDetailDAO) SaveOrderDetail() {
    fmt.Print("xml detail save")
}

//XMLDAOFactory 是RDB 抽象工厂实现
type XMLDAOFactory struct{}

func (*XMLDAOFactory) CreateOrderMainDAO() OrderMainDAO {
    return &XMLMainDAO{}
}

func (*XMLDAOFactory) CreateOrderDetailDAO() OrderDetailDAO {
    return &XMLDetailDAO{}
}

abstractfactory_test.go

package abstractfactory

func getMainAndDetail(factory DAOFactory) {
    factory.CreateOrderMainDAO().SaveOrderMain()
    factory.CreateOrderDetailDAO().SaveOrderDetail()
}

func ExampleRdbFactory() {
    var factory DAOFactory
    factory = &RDBDAOFactory{}
    getMainAndDetail(factory)
    // Output:
    // rdb main save
    // rdb detail save
}

func ExampleXmlFactory() {
    var factory DAOFactory
    factory = &XMLDAOFactory{}
    getMainAndDetail(factory)
    // Output:
    // xml main save
    // xml detail save
}

八、创建者模式
将一个复杂对象的构建分离成多个简单对象的构建组合,代码如下:
builder.go

package builder

//Builder 是生成器接口
type Builder interface {
    Part1()
    Part2()
    Part3()
}

type Director struct {
    builder Builder
}

// NewDirector ...
func NewDirector(builder Builder) *Director {
    return &Director{
        builder: builder,
    }
}

//Construct Product
func (d *Director) Construct() {
    d.builder.Part1()
    d.builder.Part2()
    d.builder.Part3()
}

type Builder1 struct {
    result string
}

func (b *Builder1) Part1() {
    b.result += "1"
}

func (b *Builder1) Part2() {
    b.result += "2"
}

func (b *Builder1) Part3() {
    b.result += "3"
}

func (b *Builder1) GetResult() string {
    return b.result
}

type Builder2 struct {
    result int
}

func (b *Builder2) Part1() {
    b.result += 1
}

func (b *Builder2) Part2() {
    b.result += 2
}

func (b *Builder2) Part3() {
    b.result += 3
}

func (b *Builder2) GetResult() int {
    return b.result
}

builder_test.go

package builder

import "testing"

func TestBuilder1(t *testing.T) {
    builder := &Builder1{}
    director := NewDirector(builder)
    director.Construct()
    res := builder.GetResult()
    if res != "123" {
        t.Fatalf("Builder1 fail expect 123 acture %s", res)
    }
}

func TestBuilder2(t *testing.T) {
    builder := &Builder2{}
    director := NewDirector(builder)
    director.Construct()
    res := builder.GetResult()
    if res != 6 {
        t.Fatalf("Builder2 fail expect 6 acture %d", res)
    }
}

九、外观模式
API 为facade 模块的外观接口,大部分代码使用此接口简化对facade类的访问。

facade模块同时暴露了a和b 两个Module 的NewXXX和interface,其它代码如果需要使用细节功能时可以直接调用。

facade.go

package facade

import "fmt"

func NewAPI() API {
    return &apiImpl{
        a: NewAModuleAPI(),
        b: NewBModuleAPI(),
    }
}

//API is facade interface of facade package
type API interface {
    Test() string
}

//facade implement
type apiImpl struct {
    a AModuleAPI
    b BModuleAPI
}

func (a *apiImpl) Test() string {
    aRet := a.a.TestA()
    bRet := a.b.TestB()
    return fmt.Sprintf("%s\n%s", aRet, bRet)
}

//NewAModuleAPI return new AModuleAPI
func NewAModuleAPI() AModuleAPI {
    return &aModuleImpl{}
}

//AModuleAPI ...
type AModuleAPI interface {
    TestA() string
}

type aModuleImpl struct{}

func (*aModuleImpl) TestA() string {
    return "A module running"
}

//NewBModuleAPI return new BModuleAPI
func NewBModuleAPI() BModuleAPI {
    return &bModuleImpl{}
}

//BModuleAPI ...
type BModuleAPI interface {
    TestB() string
}

type bModuleImpl struct{}

func (*bModuleImpl) TestB() string {
    return "B module running"
}

facade_test.go

package facade

import "testing"

var expect = "A module running\nB module running"

// TestFacadeAPI ...
func TestFacadeAPI(t *testing.T) {
    api := NewAPI()
    ret := api.Test()
    if ret != expect {
        t.Fatalf("expect %s, return %s", expect, ret)
    }
}

十、代理模式

代理模式用于延迟处理操作或者在进行实际操作前后进行其它处理。

代理模式的常见用法有
虚代理
COW代理
远程代理
保护代理
Cache 代理
防火墙代理
同步代理
智能指引
等。。。

proxy.go

package proxy

type Subject interface {
    Do() string
}

type RealSubject struct{}

func (RealSubject) Do() string {
    return "real"
}

type Proxy struct {
    real RealSubject
}

func (p Proxy) Do() string {
    var res string

    // 在调用真实对象之前的工作,检查缓存,判断权限,实例化真实对象等。。
    res += "pre:"

    // 调用真实对象
    res += p.real.Do()

    // 调用之后的操作,如缓存结果,对结果进行处理等。。
    res += ":after"

    return res
}

proxy_test.go

package proxy

import "testing"

func TestProxy(t *testing.T) {
    var sub Subject
    sub = &Proxy{}

    res := sub.Do()

    if res != "pre:real:after" {
        t.Fail()
    }
}

总结:上一篇总结了golang几个常用的设计模式,本次总结了其他设计模式的golang实现。工厂方法模式是延迟对象创建在子类里进行;抽象工厂模式是把业务能力抽象出来,使得业务实现可以简单替换就达到业务替换的目的;创建者模式是把一个复杂对象的构建分离成多个简单对象;外观模式是提供一个统一的接口来方便客户端调用系统内功能;代理模式是在原来对象的方法的前后插入一些运行逻辑。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值