什么是设计模式?

设计模式是一套理论, 由软件界先辈们总结出的一套可以反复使用的经验, 可以帮助开发人员降低代码耦合度、提高代码的重用性、扩展性和系统可维护性,以及巧妙解决一系列逻辑复杂的问题(运用套路)。然而需要注意的是,过度使用设计模式也可能会导致代码过于复杂和晦涩,因此在实际开发中需要根据具体情况进行选择和应用。

四人组(Gang of Four),简称GoF 图片经过AI修复

左到右依次是:Ralph Johnson,Erich Gamma,Richard Helm,John Vlissides。

1995年,艾瑞克·伽马(Erich Gamma)、拉尔夫·约翰森(Ralph Johnson)、理査德·海尔姆(Richard Helm)、约翰·威利斯迪斯(John Vlissides)等4位作者合作出版了《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software)一书,在本教程中收录了 23 个设计模式,这是设计模式领域里程碑的事件,导致了软件设计模式的突破。这 4 位作者在软件开发领域里也以他们的“四人组”(Gang of Four,GoF)匿名著称。

GoF将模式的概念引入软件工程领域,这标志着软件模式的诞生。软件模式(Software Patterns)是将模式的一般概念应用于软件开发领域,即软件开发的总体指导思路或参照样板。软件模式并非仅限于设计模式,还包括架构模式、分析模式和过程模式等,实际上,在软件开发生命周期的每一个阶段都存在着一些被认同的模式。软件模式与具体的应用领域无关,也就是说无论你从事的是移动应用开发、桌面应用开发、Web应用开发还是嵌入式软件的开发,都可以使用软件模式。无论你是使用Java、C#、Objective-C、VB.net、Smalltalk等纯面向对象编程语言,还是使用C++、PHP、Delphi、JavaScript等可支持面向对象编程 的语言,你都需要了解软件设计模式!“软件设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且保证代码可靠性。” (软件设计模式的定义) ——《Easy搞定Golang设计模式》

Go语言并没有将自己定位成面向对象的编程语言,但讨论23种设计模式对我们理解它也会有一定的帮助。

23种设计模式分类

23种设计模式分为三大类

创建型模式(Creational Patterns)

这些模式主要关注对象创建机制,针对具体场景选择对应方式创建对象。包含有5种设计模式

结构型模式(Structural Patterns)

这些模式主要关注对象的组合,通过单独的对象或类形成更大型的结构。包含7种设计模式

行为型模式(Behavioral Patterns)

这些模式关注的是对象间的通信,定义对象的交互方式及分配责任。包含11种设计模式

设计模式在Go的实现

创建型模式(Creational Patterns)

单例模式(Singleton Pattern)

1

工厂方法模式(Factory Method Pattern)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package factory

import "fmt"

// 定义接口
type Restaurant interface {
GetFood()
}

// 定义东来顺结构体
type Donglaishun struct {
}

// 东来顺实现GetFood方法
func (d *Donglaishun) GetFood() {
fmt.Println("东来顺饭菜准备就绪")
}

// 定义全聚德结构体
type Quanjude struct {
}

// 全聚德实现GetFood方法
func (q *Quanjude) GetFood() {
fmt.Println("全聚德烤鸭准备就绪")
}

func NewRestaurant(s string) Restaurant {
switch s {
case "d":
return &Donglaishun{}
case "q":
return &Quanjude{}
}
return nil
}

1
2
3
4
5
6
7
8
package factory

import "testing"

func TestNewRestaurant(t *testing.T) {
NewRestaurant("d").GetFood()
NewRestaurant("q").GetFood()
}
1
2
3
4
5
fei@feideMacBook-Pro 0factory % go test                  
东来顺饭菜准备就绪
全聚德烤鸭准备就绪
PASS
ok pattern/0factory 0.006s

工厂方法模式(英语:Factory method pattern)是一种实现了“工厂”概念的面向对象设计模式。就像其他创建型模式一样,它也是处理在不指定对象具体类型的情况下创建对象的问题。工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。”,实际应用中工厂方法模式针对的是一个产品等级结构。

  • 优点: 符合“开闭”原则,具有很强的的扩展性、弹性和可维护性。修改时只需要添加对应的工厂类即可使用了依赖倒置原则,依赖抽象而不是具体,使用(客户)和实现(具体类)松耦合。客户只需要知道所需产品的具体工厂,而无须知道具体工厂的创建产品的过程,甚至不需要知道具体产品的类名。
  • 缺点: 每增加一个产品时,都需要一个具体类和一个具体创建者,使得类的个数成倍增加,导致系统类数目过多,复杂性增加对简单工厂,增加功能修改的是工厂类;对工厂方法,增加功能修改的是产品类。

抽象工厂模式(Abstract Factory Pattern)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package _AbstractFactory

import "fmt"

// 定义一个午餐接口
type Lunch interface {
Cook()
}

// 定义一个米饭类
type rice struct {
}

// 米饭类实现Cook接口
func (c *rice) Cook() {
fmt.Println("it is a rice.")
}

// 定义一个西红柿类
type tomato struct {
}

// 西红柿类实现Cook接口
func (c *tomato) Cook() {
fmt.Println("it is a tomato")
}

// 定义一个午餐工厂接口
type LunchFactory interface {
CreateFood() Lunch
CreateVegetable() Lunch
}

// 定义一个美团类
type Meituan struct {
}

// 定义一个美团构造工厂
func NewMeituan() LunchFactory {
return &Meituan{}
}

// 实现创建food方法
func (m *Meituan) CreateFood() Lunch {
return &rice{}
//通过午餐interface返回米类
}

// 实现创建蔬菜方法
func (m *Meituan) CreateVegetable() Lunch {
return &tomato{}
//通过午餐interface返回西红柿类
}

1
2
3
4
5
6
7
8
9
10
11
12
13
package _AbstractFactory

import "testing"

func TestNewMeituan(t *testing.T) {
takeout := NewMeituan()
food := takeout.CreateFood()
food.Cook()

vegetable := takeout.CreateVegetable()
vegetable.Cook()
}

1
2
3
4
5
fei@feideMacBook-Pro 1AbstractFactory % go test
it is a rice.
it is a tomato
PASS
ok pattern/1AbstractFactory 0.007s

抽象工厂模式(英语:Abstract factory pattern) 是一种软件开发设计模式。抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。客户端程序不需要知道(或关心)它从这些内部的工厂方法中获得对象的具体类型,因为客户端程序仅使用这些对象的通用接口。抽象工厂模式将一组对象的实现细节与他们的一般使用分离开来。实际应用中针对的多个产品等级结构。

  • 优点: 抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。

  • 缺点: 产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的

建造者模式(Builder Pattern)

原型模式(Prototype Pattern)

结构型模式(Structural Patterns)

适配器模式(Adapter Pattern)

桥接模式(Bridge Pattern)

组合模式(Composite Pattern)

装饰器模式(Decorator Pattern)

外观模式(Facade Pattern)

享元模式(Flyweight Pattern)

代理模式(Proxy Pattern)

行为型模式(Behavioral Patterns)

责任链模式(Chain of Responsibility Pattern)

命令模式(Command Pattern)

解释器模式(Interpreter Pattern)

迭代器模式(Iterator Pattern)

中介者模式(Mediator Pattern)

备忘录模式(Memento Pattern)

观察者模式(Observer Pattern)

状态模式(State Pattern)

策略模式(Strategy Pattern)

模板方法模式(Template Method Pattern)

访问者模式(Visitor Pattern)