设计模式(Golang)

本文详细阐述了软件设计原则,如OCP、SRP、LSP等,以及在Go语言中如何应用创建型、结构型和行为型设计模式,如工厂模式、单例模式、策略模式等,以提升代码的可维护性和可扩展性。
摘要由CSDN通过智能技术生成

目录

一、设计原则

1. 开闭原则 (Open-Closed Principle, OCP)

2. 单一职责原则 (Single Responsibility Principle, SRP)

3. 里氏替换原则 (Liskov Substitution Principle, LSP)

4. 依赖倒置原则 (Dependency Inversion Principle, DIP)

5. 接口隔离原则 (Interface Segregation Principle, ISP)

6. 迪米特法则 (Law of Demeter, LoD) 或最少知识原则 (Least Knowledge Principle)

7. 合成复用原则 (Composite Reuse Principle, CRP)

二、设计模式

创建型模式

工厂模式

单例模式

建造者模式

结构型模式

适配器模式

装饰者模式

行为型模式

观察者模式

策略模式

其他模式


一、设计原则

软件设计原则是一组指导软件开发人员进行系统设计、模块划分、类和接口定义、代码组织等方面的准则,旨在提高软件的可维护性、可扩展性、灵活性和重用性。原则目的是:高类聚,低耦合。

以下是软件设计领域中广泛认可的一些核心原则: 

1. 开闭原则 (Open-Closed Principle, OCP)

类的改动是通过增加代码进行的,而不是修改源代码。

2. 单一职责原则 (Single Responsibility Principle, SRP)

类的职责单一,对外只提供一种功能,而引起类变化的原因都应该只有一个。

3. 里氏替换原则 (Liskov Substitution Principle, LSP)

任何抽象类(interface接口)出现的地方都可以用他的实现类进行替换,实际就是虚拟机制,语言级别实现面向对象功能。

4. 依赖倒置原则 (Dependency Inversion Principle, DIP)

高层模块不应依赖于低层模块,两者都应依赖于抽象(接口或抽象类),不要依赖具体的实现(类),也就是针对接口编程。

5. 接口隔离原则 (Interface Segregation Principle, ISP)

不应该强迫用户的程序依赖他们不需要的接口方法。一个接口应该只提供一种对外功能,不应该把所有操作都封装到一个接口中去。

6. 迪米特法则 (Law of Demeter, LoD) 或最少知识原则 (Least Knowledge Principle)

一个对象应当对其他对象尽可能少的了解,从而降低各个对象之间的耦合,提高系统的可维护性。例如在一个程序中,各个模块之间相互调用时,通常会提供一个统一的接口来实现。这样其他模块不需要了解另外一个模块的内部实现细节,这样当一个模块内部的实现发生改变时,不会影响其他模块的使用。(黑盒原理)

7. 合成复用原则 (Composite Reuse Principle, CRP)

如果使用继承,会导致父类的任何变换都可能影响到子类的行为。如果使用对象组合,就降低了这种依赖关系。对于继承和组合,优先使用组合。

二、设计模式

通常情况下,我们可以将常用的 23 种设计模式分为创建模式结构模式以及行为模式三种类型。

  1. 创建型(Creational)模式:如何创建对象;
  2. 结构型(Structural )模式:如何实现类或对象的组合;
  3. 行为型(Behavioral)模式:类或对象怎样交互以及怎样分配职责。
  1. 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
  2. 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  3. 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

创建型模式

工厂模式

目的:提供一个创建对象的统一接口,隐藏对象的具体创建过程。

Go 实现:使用函数或方法返回特定接口类型的实例,根据输入参数或其他条件选择创建不同类型的对象。

type Product interface {
    Operation()
}

type ConcreteProductA struct{}
func (p *ConcreteProductA) Operation() {}

type ConcreteProductB struct{}
func (p *ConcreteProductB) Operation() {}

func Factory(productType string) Product {
    switch productType {
    case "A":
        return &ConcreteProductA{}
    case "B":
        return &ConcreteProductB{}
    default:
        panic("Unknown product type")
    }
}

// 使用
product := Factory("A")
product.Operation()
单例模式

目的:确保一个类只有一个实例,并提供一个全局访问点。

Go 实现:利用 sync.Once 和全局变量确保单例对象只被初始化一次。

import "sync"

type Singleton struct{}

var (
    instance *Singleton
    once     sync.Once
)

func GetInstance() *Singleton {
    once.Do(func() {
        instance = &Singleton{}
    })
    return instance
}
建造者模式

目的:将复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。

实例:构建HTTP,设置参数header,超时时间等

Go 实现:定义一个 Builder 接口,实现多个具体的 Builder 类型,客户端通过调用 Builder 的方法逐步构造对象,最后调用 Build 方法得到完整对象。

package main

import "fmt"

type Vehicle interface {
	Describe() string
}

type CarBuilder struct {
	wheels int
	doors  int
	color  string
	engine string
}

func (cb *CarBuilder) SetWheels(wheels int) *CarBuilder {
	cb.wheels = wheels
	return cb
}
func (cb *CarBuilder) SetDoors(doors int) *CarBuilder {
	cb.doors = doors
	return cb
}
func (cb *CarBuilder) SetColor(color string) *CarBuilder {
	cb.color = color
	return cb
}
func (cb *CarBuilder) SetEngine(engine string) *CarBuilder {
	cb.engine = engine
	return cb
}

func (cb *CarBuilder) Build() Vehicle {
	return &Car{
		wheels: cb.wheels,
		doors:  cb.doors,
		color:  cb.color,
		engine: cb.engine,
	}
}

type Car struct {
	wheels int
	doors  int
	color  string
	engine string
}

func (c *Car) Describe() string {
	return fmt.Sprintf("Car with %d wheels, %d doors, color %s, engine %s",
		c.wheels, c.doors, c.color, c.engine)
}

func main() {
	// 使用
	builder := &CarBuilder{}
	builder.SetWheels(4).SetColor("Red").SetEngine("V6")
	vehicle := builder.Build()
	vehicle.Describe()
}

结构型模式

适配器模式

目的:将一个类的接口转换成客户希望的另一个接口,使得原本不兼容的类可以一起工作。

Go 实现:创建一个新的类型,该类型包含了需要适配的类型,并实现目标接口。

type Target interface {
    Request()
}

type Adaptee struct{}

func (a *Adaptee) SpecificRequest() {}

type Adapter struct {
    adaptee *Adaptee
}

func (a *Adapter) Request() {
    a.adaptee.SpecificRequest()
}

// 客户端代码使用 Target 接口,无需知道 Adapter 内部使用了 Adaptee
装饰者模式

目的:动态地给对象添加额外的责任或行为。

Go 实现:通过组合(包含)原对象,创建装饰者对象,并在装饰者中扩展或修改原对象的行为。

package main

import "fmt"

type Component interface {
	Operation() string
}

type ConcreteComponent struct{}

func (cc *ConcreteComponent) Operation() string {
	return "ConcreteComponent.Operation()"
}

type Decorator struct {
	component Component
}

func (d *Decorator) Operation() string {
	return d.component.Operation()
}

type ConcreteDecoratorA struct {
	Decorator
}

func (cd *ConcreteDecoratorA) Operation() string {
	originalOp := cd.Decorator.Operation()
	return fmt.Sprintf("ConcreteDecoratorA.Operation() -> %s", originalOp)
}

func main() {
	// 使用
	component := &ConcreteComponent{}
	decorated := &ConcreteDecoratorA{Decorator: Decorator{component: component}}
	fmt.Println(decorated.Operation())
}

行为型模式

观察者模式

目的:定义对象间一对多的依赖关系,当一个对象状态改变时,所有依赖于它的对象都会收到通知并自动更新。

Go 实现:使用 channels 和 goroutines 实现异步通知,或利用 sync.Cond 实现同步通知。

type Subject interface {
    Register(Observer)
    Unregister(Observer)
    NotifyObservers()
}

type ConcreteSubject struct {
    observers []Observer
    state     string
}

func (s *ConcreteSubject) Register(o Observer) {
    s.observers = append(s.observers, o)
}

func (s *ConcreteSubject) Unregister(o Observer) {
    // ...
}

func (s *ConcreteSubject) NotifyObservers() {
    for _, observer := range s.observers {
        go observer.Update(s.state)
    }
}

type Observer interface {
    Update(state string)
}

// 实现 Observer 接口的具体观察者
策略模式

目的:定义一系列算法,并将每个算法封装为一个单独的类,使得算法可以在运行时进行切换。

Go 实现:定义一个接口(策略),实现多个具体的策略类型,客户端根据需要选择并传递合适的策略对象。

type Strategy interface {
    Calculate(numbers []int) int
}

type AddStrategy struct{}

func (as *AddStrategy) Calculate(numbers []int) int {
    sum := 0
    for _, n := range numbers {
        sum += n
    }
    return sum
}

type MultiplyStrategy struct{}

func (ms *MultiplyStrategy) Calculate(numbers []int) int {
    product := 1
    for _, n := range numbers {
        product *= n
    }
    return product
}

func Process(numbers []int, strategy Strategy) int {
    return strategy.Calculate(numbers)
}

// 使用
result := Process([]int{1, 2, 3}, &AddStrategy{})
fmt.Println(result)  // 输出 6

result = Process([]int{1, 2, 3}, &MultiplyStrategy{})
fmt.Println(result)  // 输出 6

其他模式

除了上述示例,Go 语言中还可以实现诸如模板方法模式、命令模式、迭代器模式、中介者模式、备忘录模式、解释器模式、状态模式、访问者模式、责任链模式等。在应用设计模式时,应遵循设计原则,结合 Go 语言的特性(如接口、并发模型等),并根据具体需求进行调整和创新。

  • 22
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是几种常见的Golang设计模式: 1. 工厂模式(Factory Pattern):用于创建对象的模式,通过定义一个创建对象的接口来实现对象的实例化。 ```go type Shape interface { Draw() } type Circle struct{} func (c *Circle) Draw() { fmt.Println("Drawing a circle") } type Rectangle struct{} func (r *Rectangle) Draw() { fmt.Println("Drawing a rectangle") } type ShapeFactory struct{} func (sf *ShapeFactory) GetShape(shapeType string) Shape { if shapeType == "circle" { return &Circle{} } else if shapeType == "rectangle" { return &Rectangle{} } return nil } func main() { factory := &ShapeFactory{} circle := factory.GetShape("circle") circle.Draw() // 输出:Drawing a circle rectangle := factory.GetShape("rectangle") rectangle.Draw() // 输出:Drawing a rectangle } ``` 2. 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供一个全局访问点。 ```go type Singleton struct{} var instance *Singleton func GetInstance() *Singleton { if instance == nil { instance = &Singleton{} } return instance } func main() { singleton1 := GetInstance() singleton2 := GetInstance() fmt.Println(singleton1 == singleton2) // 输出:true } ``` 3. 观察者模式(Observer Pattern):定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。 ```go type Subject struct { observers []Observer } func (s *Subject) Attach(observer Observer) { s.observers = append(s.observers, observer) } func (s *Subject) Notify() { for _, observer := range s.observers { observer.Update() } } type Observer interface { Update() } type ConcreteObserver struct{} func (co *ConcreteObserver) Update() { fmt.Println("Observer is updated") } func main() { subject := &Subject{} observer := &ConcreteObserver{} subject.Attach(observer) subject.Notify() // 输出:Observer is updated } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值