《深入理解设计模式》记录#
这里只记录了相对常用、面试常问的设计模式。
单例模式#
单例模式(Singleton Pattern)是一种创建型设计模式,其核心目标是确保一个类仅有一个实例,并提供全局访问点。它适用于需要全局唯一对象且频繁访问的场景,例如配置管理、线程池、日志记录器等。
单例模式需要注意三点:
- 私有化构造函数:防止外部通过
new
直接创建实例。 - 自行创建实例:类内部负责生成唯一实例。
- 全局访问方法:提供静态方法供外部获取实例。
懒汉模式#
特点:延迟实例化,首次调用时创建实例,需处理线程安全问题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| package singleton
import "sync"
type lazySingleton struct {
}
var (
instance *lazySingleton
once sync.Once
)
func GetLazyInstance() *lazySingleton {
once.Do(func() {
instance = &lazySingleton{}
})
return instance
}
|
饿汉模式#
特点:在包加载时直接初始化实例,无需考虑线程安全。
1
2
3
4
5
6
7
8
9
10
11
| package singleton
type eagerSingleton struct {
}
var instance = &eagerSingleton{}
func GetEagerInstance() *eagerSingleton {
return instance
}
|
懒汉模式的另一实现形式:静态内部类#
特点:通过嵌套结构体延迟加载,结合 sync.Once
实现线程安全。
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
| package singleton
import "sync"
type holderSingleton struct {
}
var (
holderInstance *holderSingleton
holderOnce sync.Once
)
// 嵌套结构体(模拟静态内部类)
type holder struct{}
func (h *holder) getInstance() *holderSingleton {
holderOnce.Do(func() {
holderInstance = &holderSingleton{}
})
return holderInstance
}
// GetHolderInstance 对外暴露访问方法
func GetHolderInstance() *holderSingleton {
return (&holder{}).getInstance()
}
|
枚举类#
特点:利用 Go 的 init
函数和常量模拟枚举单例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| package singleton
type enumSingleton struct {
// 定义单例结构体字段
}
const (
InstanceKey = "singleton"
)
var instances = make(map[string]interface{})
func init() {
instances[InstanceKey] = &enumSingleton{}
}
// GetEnumInstance 通过键名获取单例
func GetEnumInstance() *enumSingleton {
return instances[InstanceKey].(*enumSingleton)
}
|
工厂模式#
工厂模式是一种创建型设计模式,其核心思想是通过工厂类封装对象的创建过程,降低代码耦合度,提升扩展性。
简单工厂模式#
特点:由一个工厂类根据参数决定创建哪种具体产品,客户端无需直接实例化对象。
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
| package main
// 产品接口
type Product interface {
Use() string
}
// 具体产品A
type ConcreteProductA struct{}
func (p *ConcreteProductA) Use() string {
return "Product A"
}
// 具体产品B
type ConcreteProductB struct{}
func (p *ConcreteProductB) Use() string {
return "Product B"
}
// 工厂类
type Factory struct{}
func (f *Factory) CreateProduct(typ string) Product {
switch typ {
case "A":
return &ConcreteProductA{}
case "B":
return &ConcreteProductB{}
default:
return nil
}
}
// 使用示例
func main() {
factory := Factory{}
productA := factory.CreateProduct("A")
println(productA.Use()) // 输出:Product A
}
|
工厂方法模式#
特点:定义抽象工厂接口,由子类决定实例化的具体产品,符合开闭原则。只有一个抽象产品接口、抽象工厂接口。
适用场景:产品类型较多且可能扩展,需分离创建逻辑与业务逻辑。
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
| package main
// 产品接口
type Transport interface {
Deliver() string
}
// 具体产品:卡车
type Truck struct{}
func (t *Truck) Deliver() string {
return "Delivering by land"
}
// 具体产品:轮船
type Ship struct{}
func (s *Ship) Deliver() string {
return "Delivering by sea"
}
// 抽象工厂接口
type LogisticsFactory interface {
CreateTransport() Transport
}
// 卡车工厂
type TruckFactory struct{}
func (tf *TruckFactory) CreateTransport() Transport {
return &Truck{}
}
// 轮船工厂
type ShipFactory struct{}
func (sf *ShipFactory) CreateTransport() Transport {
return &Ship{}
}
// 使用示例
func main() {
truckFactory := &TruckFactory{}
truck := truckFactory.CreateTransport()
println(truck.Deliver()) // 输出:Delivering by land
}
|
抽象工厂模式#
特点:创建多个相关或依赖的产品族(如不同品牌的全套产品),强调产品之间的关联性。由多个抽象产品接口、一个抽象工厂接口。
适用场景:需要生产一组配套对象(如不同风格的UI组件、品牌的全套硬件)。
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
| package main
// 产品接口:手机
type Phone interface {
Call() string
}
// 华为手机
type HuaweiPhone struct{}
func (h *HuaweiPhone) Call() string {
return "Huawei phone calling"
}
// 苹果手机
type IPhone struct{}
func (i *IPhone) Call() string {
return "iPhone calling"
}
// 产品接口:电脑
type Computer interface {
Work() string
}
// 华为电脑
type HuaweiComputer struct{}
func (h *HuaweiComputer) Work() string {
return "Huawei computer working"
}
// 苹果电脑
type MacBook struct{}
func (m *MacBook) Work() string {
return "MacBook working"
}
// 抽象工厂接口
type TechFactory interface {
CreatePhone() Phone
CreateComputer() Computer
}
// 华为工厂
type HuaweiFactory struct{}
func (hf *HuaweiFactory) CreatePhone() Phone {
return &HuaweiPhone{}
}
func (hf *HuaweiFactory) CreateComputer() Computer {
return &HuaweiComputer{}
}
// 苹果工厂
type AppleFactory struct{}
func (af *AppleFactory) CreatePhone() Phone {
return &IPhone{}
}
func (af *AppleFactory) CreateComputer() Computer {
return &MacBook{}
}
// 使用示例
func main() {
factory := &HuaweiFactory{}
phone := factory.CreatePhone()
computer := factory.CreateComputer()
println(phone.Call(), computer.Work()) // 输出:Huawei phone calling Huawei computer working
}
|
原型模式#
原型模式(Prototype Pattern)是一种创建型设计模式,其核心思想是通过复制现有对象(原型)来生成新对象,而非通过传统的类实例化方式(如new
关键字)。
原型模式通过克隆机制创建对象,允许一个对象作为原型,基于其生成新实例。这种方式避免了重复初始化带来的性能损耗,尤其当对象包含复杂数据结构或依赖外部资源时。
原型模式的实现有两种:
- 浅拷贝:仅复制对象的基本类型属性和引用地址,不复制引用指向的实际对象。所有克隆对象共享同一引用成员。
- 深拷贝:递归复制所有引用类型成员,确保克隆对象与原对象完全独立。
适配器模式#
适配器模式用于解决接口不兼容的问题,通过将一个类的接口转换成客户端期望的另一个接口,使得原本不兼容的类可以协同工作。
适配器模式由三部分组成:
适配器模式适合应用于整合旧系统、第三方库兼容等场景,能提高代码复用性。
类适配器#
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
| package main
import "fmt"
// --- 目标接口 ---
type USB interface {
Connect()
}
// --- 被适配者 ---
type TypeC struct{}
func (t *TypeC) TypeCConnect() {
fmt.Println("TypeC connected.")
}
// --- 适配器(对象适配器,通过组合实现)---
type TypeCToUSBAdapter struct {
typeC *TypeC
}
func NewTypeCToUSBAdapter(typeC *TypeC) *TypeCToUSBAdapter {
return &TypeCToUSBAdapter{typeC: typeC}
}
func (a *TypeCToUSBAdapter) Connect() {
a.typeC.TypeCConnect() // 调用被适配者的方法
}
// 使用示例
func main() {
typeC := &TypeC{}
usbAdapter := NewTypeCToUSBAdapter(typeC)
usbAdapter.Connect() // 输出: TypeC connected.
}
|
装饰器模式#
装饰器模式通过动态地给对象添加额外的职责,提供比继承更灵活的扩展方式。
装饰器模式灵活扩展对象功能,支持运行时动态组合,且符合单一职责原则(每个装饰器只关注一个功能)。
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
55
56
57
58
59
60
61
62
| package main
import "fmt"
// --- 组件接口 ---
type Coffee interface {
Cost() float64
Description() string
}
// --- 具体组件 ---
type BlackCoffee struct{}
func (b *BlackCoffee) Cost() float64 {
return 2.0
}
func (b *BlackCoffee) Description() string {
return "Black Coffee"
}
// --- 装饰器基类(通过嵌套接口实现)---
type CoffeeDecorator struct {
coffee Coffee
}
func (d *CoffeeDecorator) Cost() float64 {
return d.coffee.Cost()
}
func (d *CoffeeDecorator) Description() string {
return d.coffee.Description()
}
// --- 具体装饰器:加牛奶 ---
type MilkDecorator struct {
CoffeeDecorator
}
func NewMilkDecorator(coffee Coffee) *MilkDecorator {
return &MilkDecorator{CoffeeDecorator{coffee: coffee}}
}
func (m *MilkDecorator) Cost() float64 {
return m.coffee.Cost() + 0.5
}
func (m *MilkDecorator) Description() string {
return m.coffee.Description() + ", Milk"
}
// 使用示例
func main() {
var coffee Coffee
coffee = &BlackCoffee{}
fmt.Printf("Cost: %.1f, Description: %s\n", coffee.Cost(), coffee.Description())
// 输出: Cost: 2.0, Description: Black Coffee
coffee = NewMilkDecorator(coffee)
fmt.Printf("Cost: %.1f, Description: %s\n", coffee.Cost(), coffee.Description())
// 输出: Cost: 2.5, Description: Black Coffee, Milk
}
|
代理模式#
代理模式是一种结构型设计模式,通过引入一个代理对象来控制对真实对象的访问,实现功能增强或访问控制。其核心在于解耦客户端与真实对象,代理对象与真实对象实现相同接口,客户端通过代理间接操作真实对象。
代理模式的结构如下:
- 抽象主题:定义代理和真实对象的公共接口(如图片加载接口)。
- 真实主题:实际执行业务逻辑的类。
- 代理:实现相同接口,控制对真实对象的访问(如权限检查、延迟加载)。
- 客户端。
使用代理模式可以使代码职责清晰、扩展性强(如新增日志功能无需修改真实对象)、保护真实对象,缺陷就是可能增加类数量(静态代理)、动态代理需反射机制可能影响性能。
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
| package main
import "fmt"
// 接口定义
type Vehicle interface { Drive() }
// 真实对象
type Car struct{}
func (c *Car) Drive() { fmt.Println("Car is being driven") }
// 代理对象
type CarProxy struct {
vehicle Vehicle
driver *Driver
}
type Driver struct{ Age int }
func NewCarProxy(driver *Driver) *CarProxy {
return &CarProxy{&Car{}, driver}
}
func (p *CarProxy) Drive() {
if p.driver.Age >= 16 {
p.vehicle.Drive()
} else {
fmt.Println("Driver too young!")
}
}
// 客户端
func main() {
proxy := NewCarProxy(&Driver{12})
proxy.Drive() // 输出: Driver too young!
proxy = NewCarProxy(&Driver{22})
proxy.Drive() // 输出: Car is being driven
}
|
策略模式#
策略模式是一种行为型设计模式,将一组算法封装为独立策略类,使客户端能动态切换算法。其核心是通过组合而非继承实现行为的灵活扩展。
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
| package main
import "fmt"
// 策略接口
type PricingStrategy interface { CalculatePrice(float64) float64 }
// 具体策略
type RegularStrategy struct{}
func (s *RegularStrategy) CalculatePrice(p float64) float64 { return p }
type VIPStrategy struct{}
func (s *VIPStrategy) CalculatePrice(p float64) float64 { return p * 0.9 }
// 上下文
type PricingService struct{ strategy PricingStrategy }
func (s *PricingService) SetStrategy(strategy PricingStrategy) { s.strategy = strategy }
func (s *PricingService) Calculate(p float64) float64 { return s.strategy.CalculatePrice(p) }
// 客户端
func main() {
service := &PricingService{}
service.SetStrategy(&RegularStrategy{})
fmt.Println(service.Calculate(100)) // 输出: 100
service.SetStrategy(&VIPStrategy{})
fmt.Println(service.Calculate(100)) // 输出: 90
}
|
命令模式#
命令模式是一种行为型设计模式,将请求封装为对象,支持请求的排队、撤销和日志记录。核心在于解耦请求发送者与接收者,通过命令对象统一管理操作。
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
| package main
import "fmt"
// 命令接口
type Command interface{ Execute() }
// 具体命令
type TVOnCommand struct{ tv *TV }
func (c *TVOnCommand) Execute() { c.tv.On() }
type TVOffCommand struct{ tv *TV }
func (c *TVOffCommand) Execute() { c.tv.Off() }
// 接收者
type TV struct{}
func (t *TV) On() { fmt.Println("TV on") }
func (t *TV) Off() { fmt.Println("TV off") }
// 调用者
type RemoteControl struct{ cmd Command }
func (r *RemoteControl) SetCommand(cmd Command) { r.cmd = cmd }
func (r *RemoteControl) Press() { r.cmd.Execute() }
// 客户端
func main() {
tv := &TV{}
remote := &RemoteControl{}
remote.SetCommand(&TVOnCommand{tv})
remote.Press() // 输出: TV on
remote.SetCommand(&TVOffCommand{tv})
remote.Press() // 输出: TV off
}
|