设计模式(一)| 青训营笔记

88 阅读3分钟

之前一个非常友善的面试官推荐我好好学习一下设计模式,可以提升眼界、改变思考问题的方式,所以找了《设计模式-可复用面向对象软件的基础》一书,虽然其中的代码示例都是C++,但读下来还是有很多收获,这里用go语言写一下我学习到的东西

设计模式一共有23种,可以分为三大类:创建型设计模式、结构型设计模式和行为型设计模式

1. 单例模式

单例模式是一种创建型设计模式,其目的是确保一个类只有一个实例,并提供对该实例的全局访问点。单例模式通常用于控制资源访问,例如数据库连接池或线程池。

在 Go 语言中,可以通过使用 sync 包提供的 Once 类型来实现单例模式。Once 可以确保函数仅被执行一次,即保证一个实例只会被创建一次。示例代码如下:

package singleton

import "sync"

type MySingleton struct {
    data string
}

var myInstance *MySingleton
var once sync.Once

// GetInstance 获取 MySingleton 的唯一实例
func GetInstance() *MySingleton {
    // 使用 sync.Once 实现懒加载单例
    once.Do(func() {
        myInstance = &MySingleton{"my data"}
    })
    return myInstance
}

上述代码中,我们定义了一个 MySingleton 类型和一个全局变量 myInstance,用于存储单例实例。在 GetInstance 函数中,我们使用 sync.Once 实现了单例实例的懒汉式加载方式,即只有第一次调用 GetInstance 函数时才会创建单例实例。

2. 工厂方法模式

工厂方法模式是一种创建型设计模式,其目的是定义一个接口或抽象类,其中包含用于创建对象的工厂方法。在运行时,通过选择合适的工厂方法使得产生的对象符合特定的使用场景。

在 Go 语言中,可以通过定义一个接口或结构体以及相应的工厂函数来实现工厂方法模式。示例代码如下:

package factory

// Product 是产品接口
type Product interface {
    GetName() string
}

// ProductA 是产品 A 的具体实现
type ProductA struct {}

func (p *ProductA) GetName() string {
    return "ProductA"
}

// Factory 是工厂接口
type Factory interface {
    CreateProduct() Product
}

// FactoryA 是工厂 A 的具体实现,用于创建 ProductA
type FactoryA struct {}

func (f *FactoryA) CreateProduct() Product {
    return &ProductA{}
}    

上述代码中,我们定义了 Product 接口和相应的实现 ProductA,其中 GetName 方法用于返回产品名称。接着定义了一个 Factory 接口以及对应的工厂函数,用于创建具体的产品实例。

3. 抽象工厂模式

抽象工厂模式是一种创建型设计模式,其目的是为创建相关或依赖对象的组合提供接口。抽象工厂允许客户端使用抽象接口来创建一组相关的对象,而不需要知道或关心它们的具体实现。

在 Go 语言中,可以通过实现抽象工厂接口和相应的具体工厂来实现抽象工厂模式。示例代码如下:

package abstractfactory

// ProductA 是产品 A 接口
type ProductA interface {
    GetName() string
    GetPrice() float64
}

// ProductB 是产品 B 接口
type ProductB interface {
    GetName() string
    GetWeight() float64
}

// Factory 是工厂接口
type Factory interface {
    CreateProductA() ProductA
    CreateProductB() ProductB
}

// Factory1 是工厂 1 的具体实现
type Factory1 struct {}

func (f *Factory1) CreateProductA() ProductA {
    return &ProductA1{}
}

func (f *Factory1) CreateProductB() ProductB {
    return &ProductB1{}
}

// ProductA1 是产品 A1 的具体实现
type ProductA1 struct {}

func (p *ProductA1) GetName() string {
    return "ProductA1"
}

func (p *ProductA1) GetPrice() float64 {
    return 10.0
}

// ProductB1 是产品 B1 的具体实现
type ProductB1 struct {}

func (p *ProductB1) GetName() string {
    return "ProductB1"
}

func (p *ProductB1) GetWeight() float64 {
    return 1.0
}

上述代码中,我们定义了两个产品接口 ProductA 和 ProductB,以及对应的实现类 ProductA1 和 ProductB1。接着定义了一个抽象工厂 Factory,包含两个工厂方法 CreateProductA 和 CreateProductB,分别用于创建 ProductA 和 ProductB 的实例。最后定义了一个具体工厂 Factory1,它实现了 Factory 接口,可以创建 ProductA1 和 ProductB1 的实例。