go中设计模式之结构型模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go中设计模式之结构型模式相关的知识,希望对你有一定的参考价值。

外观模式

1. 定义: 外部与一个子系统通信必须通过一个统一的对象进行,为子系统中的一组接口提供一致界面。

2. 代码示例:

// 定义对外API
type API interface 
    Test()


func NewAPI() API 
    return apiImplnewMod()


type apiImpl struct 
    m mod


func (a apiImpl) Test() 
    a.m.mod()


// 需要交互的内部模块
type mod interface 
    mod()


func newMod() mod 
    return modImpl


type modImpl struct 


func (m modImpl) mod() 


3. 实现步骤

  • 定义内部模块
  • 定义对外交互接口及实现

4. 使用场景

  • 当要为一个复杂子系统提供一个简单接口时可以使用外观模式。该接口可以满足大多数用户的需求,而且用户也可以越过外观类直接访问子系统。
  • 客户程序与多个子系统之间存在很大的依赖性。引入外观类将子系统与客户以及其他子系统解耦,可以提高子系统的独立性和可移植性。
  • 在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。

5. 优点

对客户屏蔽子系统组件

适配器模式

1. 定义: 将一个接口转换成客户希望的另一个接口。

2. 代码示例:

// 定义被适配的接口
type Adapter interface 
    Request() string


type adaptee struct 


func (adaptee) Request() string 


func NewAdapter() Adapter 
    return &adaptee


// 定义目标接口
type Target interface 
    TargetRequest() string


func New(adapter Adapter) Target 
    return &targetadapter


type target struct 
    Adapter


func (t *target) TargetRequest() 
    t.Request()

3. 实现步骤

  • 定义被适配的接口和实现
  • 定义目标接口和实现,并且实现接口由被适配接口创建

4. 使用场景

系统需要使用现有的类,而这些类的接口不符合系统的需要。

5. 优点

将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。

装饰模式

1. 定义: 动态地给一个对象增加一些额外的职责。

2. 代码示例:

// 定义组件
type Component interface 
    Calc() int


type ConcreteComponent struct

func (*ConcreteComponent) Calc() int 
    return 0


// 定义装饰对象
type MulDecorator struct 
    Component
    num int


func WarpMulDecorator(c Component, num int) Component 
    return &MulDecorator
        Component: c,
        num:       num,
    


func (d *MulDecorator) Calc() int 
    return d.Component.Calc() * d.num


type AddDecorator struct 
    Component
    num int


func WarpAddDecorator(c Component, num int) Component 
    return &AddDecorator
        Component: c,
        num:       num,
    


func (d *AddDecorator) Calc() int 
    return d.Component.Calc() + d.num

3. 实现步骤

  • 定义组件
  • 定义装饰对象
  • 使用装饰对象生成组件

4. 使用场景

在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

5. 优点

可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为。

享元模式

1. 定义: 享元模式通过共享技术实现相同或相似对象的重用。

2. 代码示例:

// 定义享元对象
type ImageFlyweight struct 
    data string


func NewImageFlyweight(filename string) *ImageFlyweight 
    // Load image file
    data := fmt.Sprintf("image data %s", filename)
    return &ImageFlyweight
        data: data,
    


func (i *ImageFlyweight) Data() string 
    return i.data


// 定义享元对象工厂
type ImageFlyweightFactory struct 
    maps map[string]*ImageFlyweight


var imageFactory *ImageFlyweightFactory

func GetImageFlyweightFactory() *ImageFlyweightFactory 
    if imageFactory == nil 
        imageFactory = &ImageFlyweightFactory
            maps: make(map[string]*ImageFlyweight),
        
    
    return imageFactory


func (f *ImageFlyweightFactory) Get(filename string) *ImageFlyweight 
    image := f.maps[filename]
    if image == nil 
        image = NewImageFlyweight(filename)
        f.maps[filename] = image
    

    return image


type ImageViewer struct 
    *ImageFlyweight


func NewImageViewer(filename string) *ImageViewer 
    image := GetImageFlyweightFactory().Get(filename)
    return &ImageViewer
        ImageFlyweight: image,
    


func (i *ImageViewer) Display() 
    fmt.Printf("Display: %s\n", i.Data())

3. 实现步骤

  • 定义享元对象
  • 定义享元工厂
  • 使用享元工厂创建

4. 使用场景

  • 一个系统有大量相同或者相似的对象,由于这类对象的大量使用,造成内存的大量耗费。
    对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
  • 使用享元模式需要维护一个存储享元对象的享元池,而这需要耗费资源,因此,应当在多次重复使用享元对象时才值得使用享元模式。

5. 优点

享元模式从对象中剥离出不发生改变且多个实例需要的重复数据,独立出一个享元,使多个对象共享,从而节省内存以及减少对象数量。

代理模式

1. 定义: 给某一个对象提供一个代理,并由代理对象控制对原对象的引用。

2. 代码示例:

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

3. 实现步骤

  • 定义接口
  • 定义实现对象
  • 定义代理实现对象

4. 使用场景

  • 并由代理对象控制对原对象的引用,增加请求注入劫持

5. 优点

代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。

桥接模式

1. 定义: 给某一个对象提供一个代 理,并由代理对象控制对原对象的引用。

2. 代码示例:

package bridge

import "fmt"

type AbstractMessage interface 
    SendMessage(text, to string)


type MessageImplementer interface 
    Send(text, to string)


type MessageSMS struct

func ViaSMS() MessageImplementer 
    return &MessageSMS


func (*MessageSMS) Send(text, to string) 
    fmt.Printf("send %s to %s via SMS", text, to)


type MessageEmail struct

func ViaEmail() MessageImplementer 
    return &MessageEmail


func (*MessageEmail) Send(text, to string) 
    fmt.Printf("send %s to %s via Email", text, to)


type CommonMessage struct 
    method MessageImplementer


func NewCommonMessage(method MessageImplementer) *CommonMessage 
    return &CommonMessage
        method: method,
    


func (m *CommonMessage) SendMessage(text, to string) 
    m.method.Send(text, to)


type UrgencyMessage struct 
    method MessageImplementer


func NewUrgencyMessage(method MessageImplementer) *UrgencyMessage 
    return &UrgencyMessage
        method: method,
    


func (m *UrgencyMessage) SendMessage(text, to string) 
    m.method.Send(fmt.Sprintf("[Urgency] %s", text), to)

3. 实现步骤

4. 使用场景

5. 优点

以上是关于go中设计模式之结构型模式的主要内容,如果未能解决你的问题,请参考以下文章

Go语言实现的23种设计模式之结构型模式

[设计模式C++go]结构型模式:代理模式

[设计模式C++go]结构型模式:代理模式

[设计模式C++go]结构型模式:代理模式

go解锁设计模式之单例模式

[设计模式C++go]结构型模式:桥接模式