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

栏目: Go · 发布时间: 6年前

内容简介:1. 定义: 外部与一个子系统通信必须通过一个统一的对象进行,为子系统中的一组接口提供一致界面。对客户屏蔽子系统组件系统需要使用现有的类,而这些类的接口不符合系统的需要。

外观模式

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

2. 代码示例:

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

func NewAPI() API {
    return apiImpl{newMod()}
}

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 &target{adapter}
}

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. 优点


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Music Recommendation and Discovery

Music Recommendation and Discovery

Òscar Celma / Springer / 2010-9-7 / USD 49.95

With so much more music available these days, traditional ways of finding music have diminished. Today radio shows are often programmed by large corporations that create playlists drawn from a limited......一起来看看 《Music Recommendation and Discovery》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

html转js在线工具
html转js在线工具

html转js在线工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换