1. 前言 🍈
因为很早之前就不写java了,再加上后面的工作一直以业务为主,导致对设计模式了解甚少。(其实就是没用过设计模式!orz)
最近在工作和学习源码中,都遇到了设计模式的问题,而我竟然不会,这就很难受!因此,在这篇文章里,我要实现23种常见的设计模式,尽可能列出它们的使用场景,以此来凸显我的厉害!
常见的23种设计模式可以被分类为三种:创建型、结构型和行为型。
创建型模式5个:
单例模式(Singleton)、抽象工厂模式(Abstract Factory)、建造者模式(Builder)、工厂模式(Factory)、原型模式(Prototype)。
结构型模式7个:
适配器模式(Adapter)、桥接模式(Bridge)、装饰模式(Decorator)、组合模式(Composite)、外观模式(Facade)、享元模式(Flyweight)、代理模式(Proxy)。
行为型模式11个:
模版方法模式(Template Method)、命令模式(Command)、迭代器模式(Iterator)、观察者模式(Observer)、中介者模式(Mediator)、备忘录模式(Memento)、解释器模式(Interpreter)、状态模式(State)、策略模式(Strategy)、责任链模式(Chain of Responsibility)、访问者模式(Visitor)。
💡 一切用图来说话
2. 创建型模式 🍉
单例模式
GoF 对单例模式(Singleton)的定义如下:
Ensure a class only has one instance, and provide a global point of access to it.
单例模式会保证每个class都只有一个实例,并且提供一个全局的访问点。
通常情况下,被建模成单例的对象都有“中心点”的含义,例如:线程池是管理线程的中心、全局配置是读取配置的中心。
在实现单例时,通常有两种模式:饿汉模式和懒汉模式。前者是在初始化时就完成了单例的初始化;后者是在调用时才进行初始化,从会节约一定的内存,但会带来并发问题。
示例:
package singleton
import (
"sync"
)
var once sync.Once //sync.Once可保证方法只被执行一次
var single *singleton //单例对象
type singleton struct {
name string
}
func New(name string) *singleton {
if single == nil { //初始化
once.Do(func() {
single = &singleton{
name: name,
}
})
}
return single
}
func (s *singleton) String() string {
return s.name
}
应用场景:
- 日志。每个服务通常都会需要一个全局的日志对象来记录本服务产生的日志。
- 全局配置。对于一些全局的配置,可以通过定义一个单例来供客户端使用。
- 唯一序列号生成。唯一序列号生成必然要求整系统只能有一个生成实例,非常合适使用单例模式。
- 线程池、对象池、连接池等。xxx池的本质就是共享,也是单例模式的常见场景。
- 全局缓存
- ……
工厂模式
工厂模式允许调用者传参,从而返回相应的对象。但工厂模式一般只适用于简单的业务场景。因为,要增加产品时,就要修改switch中的代码,违反了开放封闭原则。
示例:
package factory
import (
"fmt"
)
type Car interface {
Drive()
}
type bmw struct {
}
func (b *bmw) Drive() {
fmt.Println("正在驾驶宝马车...")
}
type tesla struct {
}
func (t *tesla) Drive() {
fmt.Println("正在驾驶特斯拉...")
}
type byd struct {
}
func (d *byd) Drive() {
fmt.Println("正在驾驶比亚迪...")
}
func FactoryCreateCar(car string) Car {
//根据参数的类型返回对应的car
switch car {
case "tesla":
return &tesla{}
case "bmw":
return &bmw{}
case "byd":
return &byd{}
}
return nil
}
应用场景:
略