软件设计模式
定义:软件设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结, 目的:是为了可重复代码、让代码更容易被他人理解并且保证代码可靠性
面向对象原则
高内聚,低耦合
设计模式种类
1. 创建型模式(如何创建对象)
简单工厂模式(违背开闭原则)
通过一个工厂类来创建不同类型的对象,而不需要直接暴露对象的创建逻辑给客户端。简单工厂模式隐藏了对象的创建过程,使得客户端只需要通过工厂类来获取所需的对象实例。
- 工厂类(Factory):负责创建对象的类。它根据客户端的请求,创建相应的对象并返回给客户端。
- 抽象产品类(Product):定义了产品的共同接口,它描述了产品具有的属性和方法。
- 具体产品类(Concrete Product):实现了抽象产品类的接口,是被工厂类创建的对象。
package main
import "fmt"
// 接口:产品
type Product interface {
Use()
}
// 具体产品类型A
type ProductA struct{}
func (p *ProductA) Use() {
fmt.Println("Product A is being used")
}
// 具体产品类型B
type ProductB struct{}
func (p *ProductB) Use() {
fmt.Println("Product B is being used")
}
// 简单工厂
type SimpleFactory struct{}
func (f *SimpleFactory) CreateProduct(productType string) Product {
switch productType {
case "A":
return &ProductA{}
case "B":
return &ProductB{}
default:
return nil
}
}
func main() {
factory := &SimpleFactory{}
// 创建产品A
productA := factory.CreateProduct("A")
productA.Use()
// 创建产品B
productB := factory.CreateProduct("B")
productB.Use()
}
抽象工厂模式
提供了一种方式来创建一系列相关或相互依赖的对象,而无需指定其具体的类
- 抽象工厂(Abstract Factory):定义了一组创建产品对象的方法,每个方法对应一个具体的产品族。客户端通过调用这些方法来创建所需的产品对象。
- 具体工厂(Concrete Factory):实现了抽象工厂接口,负责创建具体的产品对象。每个具体工厂类对应一个具体的产品族。
- 抽象产品(Abstract Product):定义了产品对象的接口,描述了产品的共同属性和方法。
- 具体产品(Concrete Product):实现了抽象产品接口,是由具体工厂创建的对象。
package main
import "fmt"
// 抽象产品A接口
type ProductA interface {
UseA()
}
// 具体产品A1
type ProductA1 struct{}
func (p *ProductA1) UseA() {
fmt.Println("Product A1 is being used")
}
// 具体产品A2
type ProductA2 struct{}
func (p *ProductA2) UseA() {
fmt.Println("Product A2 is being used")
}
// 抽象产品B接口
type ProductB interface {
UseB()
}
// 具体产品B1
type ProductB1 struct{}
func (p *ProductB1) UseB() {
fmt.Println("Product B1 is being used")
}
// 具体产品B2
type ProductB2 struct{}
func (p *ProductB2) UseB() {
fmt.Println("Product B2 is being used")
}
// 抽象工厂接口
type AbstractFactory interface {
CreateProductA() ProductA
CreateProductB() ProductB
}
// 具体工厂1
type ConcreteFactory1 struct{}
func (f *ConcreteFactory1) CreateProductA() ProductA {
return &ProductA1{}
}
func (f *ConcreteFactory1) CreateProductB() ProductB {
return &ProductB1{}
}
// 具体工厂2
type ConcreteFactory2 struct{}
func (f *ConcreteFactory2) CreateProductA() ProductA {
return &ProductA2{}
}
func (f *ConcreteFactory2) CreateProductB() ProductB {
return &ProductB2{}
}
func main() {
// 使用具体工厂1创建产品A和产品B
factory1 := &ConcreteFactory1{}
productA1 := factory1.CreateProductA()
productB1 := factory1.CreateProductB()
productA1.UseA()
productB1.UseB()
// 使用具体工厂2创建产品A和产品B
factory2 := &ConcreteFactory2{}
productA2 := factory2.CreateProductA()
productB2 := factory2.CreateProductB()
productA2.UseA()
productB2.UseB()
}
单例模式
确保一个类只有一个实例,并提供一个全局访问点来访问该实例。
package main
import (
"fmt"
"sync"
)
// 单例对象
type Singleton struct {
data string
}
// 单例对象的实例
var instance *Singleton
// 用于保证线程安全的锁和一次性执行
var once sync.Once
// 获取单例对象的方法
func GetInstance() *Singleton {
once.Do(func() {
instance = &Singleton{data: "Hello, Singleton!"}
})
return instance
}
func main() {
// 获取单例对象
singleton := GetInstance()
// 使用单例对象
fmt.Println(singleton.data)
}
2. 结构型模式(如何实现类或对象的组合)
代理模式
允许通过一个代理对象来控制对真实对象的访问
- 抽象主题(Abstract Subject):定义了真实主题和代理主题的共同接口,这样代理类就可以在任何使用真实主题的地方替代它。
- 真实主题(Real Subject):实现了抽象主题接口,是代理所代表的真实对象,是客户端所关心的对象。
- 代理主题(Proxy Subject):实现了抽象主题接口,包含一个指向真实主题的引用,可以控制对真实主题的访问,并在访问前后执行额外的操作。
package main
import "fmt"
// 接口:主题
type Subject interface {
Request()
}
// 具体主题
type ConcreteSubject struct{}
func (s *ConcreteSubject) Request() {
fmt.Println("ConcreteSubject handles the request")
}
// 代理
type Proxy struct {
subject Subject
}
func (p *Proxy) Request() {
// 在调用具体主题前后可以添加额外的逻辑
fmt.Println("Proxy handles the request before")
p.subject.Request()
fmt.Println("Proxy handles the request after")
}
func main() {
// 创建具体主题
subject := &ConcreteSubject{}
// 创建代理,并将具体主题作为参数传入
proxy := &Proxy{
subject: subject,
}
// 通过代理调用请求
proxy.Request()
}
装饰器模式
不改变原有对象接口的情况下,动态地扩展对象的功能
- 抽象构件(Component):定义了原始对象和装饰器对象的共同接口,可以是抽象类或接口。
- 具体构件(Concrete Component):实现了抽象构件接口,是需要被装饰的原始对象。
- 抽象装饰器(Decorator):继承了抽象构件接口,并持有一个抽象构件的引用,用于包装原始对象。
- 具体装饰器(Concrete Decorator):继承了抽象装饰器,并实现了额外的功能。它可以在调用原始对象的方法之前或之后执行一些操作,以扩展原始对象的功能。
package main
import "fmt"
// 接口:组件
type Component interface {
Operation()
}
// 具体组件
type ConcreteComponent struct{}
func (c *ConcreteComponent) Operation() {
fmt.Println("ConcreteComponent operation")
}
// 装饰器
type Decorator struct {
component Component
}
func (d *Decorator) Operation() {
// 在调用具体组件前后可以添加额外的逻辑
fmt.Println("Decorator operation before")
d.component.Operation()
fmt.Println("Decorator operation after")
}
func main() {
// 创建具体组件
component := &ConcreteComponent{}
// 创建装饰器,并将具体组件作为参数传入
decorator := &Decorator{
component: component,
}
// 通过装饰器调用操作
decorator.Operation()
}
适配器模式
将一个类的接口转换成客户端所期望的另一个接口
- 目标接口(Target Interface):定义了客户端期望的接口,客户端通过这个接口与适配器进行交互。
- 适配器(Adapter):实现了目标接口,同时持有一个适配者对象的引用。适配器将客户端的请求转发给适配者对象来完成实际的操作。
- 适配者(Adaptee):原本已经存在的类,包含了客户端所需要的功能,但与目标接口不兼容。
package main
import "fmt"
// 目标接口
type Target interface {
Request()
}
// 源接口
type Adaptee interface {
SpecificRequest()
}
// 源类型
type ConcreteAdaptee struct{}
func (a *ConcreteAdaptee) SpecificRequest() {
fmt.Println("Specific request")
}
// 适配器
type Adapter struct {
adaptee Adaptee
}
func (a *Adapter) Request() {
// 调用适配者的方法来实现目标接口的方法
a.adaptee.SpecificRequest()
}
func main() {
// 创建适配者
adaptee := &ConcreteAdaptee{}
// 创建适配器,并将适配者作为参数传入
adapter := &Adapter{
adaptee: adaptee,
}
// 通过适配器调用目标接口方法
adapter.Request()
}
外观模式
提供了一个统一的接口,用于访问子系统中一组接口的功能
- 外观(Facade):提供了一个简化的接口,用于访问子系统中一组接口的功能。它知道哪些子系统类负责处理客户端的请求,将请求委派给相应的子系统对象进行处理。
- 子系统类(Subsystem Classes):实现了子系统的功能,处理外观对象指派的任务。子系统类可以是单个类,也可以是一组相关的类。
package main
import "fmt"
// 子系统A
type SubsystemA struct{}
func (s *SubsystemA) OperationA() {
fmt.Println("Subsystem A operation")
}
// 子系统B
type SubsystemB struct{}
func (s *SubsystemB) OperationB() {
fmt.Println("Subsystem B operation")
}
// 外观
type Facade struct {
subsystemA *SubsystemA
subsystemB *SubsystemB
}
func NewFacade() *Facade {
return &Facade{
subsystemA: &SubsystemA{},
subsystemB: &SubsystemB{},
}
}
func (f *Facade) Operation() {
// 调用子系统的方法
f.subsystemA.OperationA()
f.subsystemB.OperationB()
}
func main() {
// 创建外观
facade := NewFacade()
// 通过外观调用操作
facade.Operation()
}
组合模式
将对象组合成树状结构,以表示部分-整体的层次结构
- 抽象构件(Component):定义了组合中的对象共有的接口,可以是抽象类或接口。它声明了访问和管理子对象的方法,以及一些默认的行为。
- 叶子构件(Leaf):表示树中的叶子节点,没有子节点。实现了抽象构件的接口。
- 组合构件(Composite):表示树中的分支节点,具有子节点。实现了抽象构件的接口,并提供了管理子节点的方法。
package main
import "fmt"
// 抽象组件接口
type Component interface {
Operation()
}
// 叶子节点
type Leaf struct {
name string
}
func (l *Leaf) Operation() {
fmt.Println("Leaf", l.name, "operation")
}
// 组合节点
type Composite struct {
name string
components []Component
}
func (c *Composite) Operation() {
fmt.Println("Composite", c.name, "operation")
// 遍历并调用子组件的操作方法
for _, component := range c.components {
component.Operation()
}
}
func (c *Composite) Add(component Component) {
c.components = append(c.components, component)
}
func (c *Composite) Remove(component Component) {
for i, comp := range c.components {
if comp == component {
c.components = append(c.components[:i], c.components[i+1:]...)
break
}
}
}
func main() {
// 创建树状结构
root := &Composite{name: "root"}
leaf1 := &Leaf{name: "leaf1"}
leaf2 := &Leaf{name: "leaf2"}
subComposite := &Composite{name: "subComposite"}
subLeaf := &Leaf{name: "subLeaf"}
root.Add(leaf1)
root.Add(leaf2)
root.Add(subComposite)
subComposite.Add(subLeaf)
// 调用根节点的操作方法,会递归执行子节点的操作方法
root.Operation()
}
桥接模式
将抽象部分和实现部分分离,使它们可以独立地变化和扩展
- 抽象部分(Abstraction):定义了抽象部分的接口,并维护一个指向实现部分的引用。它通常包含抽象部分的业务逻辑。
- 实现部分(Implementation):定义了实现部分的接口,提供了实现部分的具体实现。
- 具体抽象部分(Concrete Abstraction):继承自抽象部分,实现了抽象部分的接口,并调用实现部分的具体实现。
- 具体实现部分(Concrete Implementation):继承自实现部分,实现了实现部分的接口。
package main
import "fmt"
// 实现者接口
type Implementor interface {
OperationImpl()
}
// 具体实现者A
type ConcreteImplementorA struct{}
func (c *ConcreteImplementorA) OperationImpl() {
fmt.Println("Concrete Implementor A operation")
}
// 具体实现者B
type ConcreteImplementorB struct{}
func (c *ConcreteImplementorB) OperationImpl() {
fmt.Println("Concrete Implementor B operation")
}
// 抽象类
type Abstraction struct {
implementor Implementor
}
func (a *Abstraction) SetImplementor(implementor Implementor) {
a.implementor = implementor
}
func (a *Abstraction) Operation() {
if a.implementor != nil {
a.implementor.OperationImpl()
}
}
// 客户端代码
func main() {
// 创建抽象类对象
abstraction := &Abstraction{}
// 创建具体实现者对象
implementorA := &ConcreteImplementorA{}
implementorB := &ConcreteImplementorB{}
// 将具体实现者A关联到抽象类对象
abstraction.SetImplementor(implementorA)
// 调用抽象类的操作方法,实际上执行的是具体实现者A的方法
abstraction.Operation()
// 将具体实现者B关联到抽象类对象
abstraction.SetImplementor(implementorB)
// 调用抽象类的操作方法,实际上执行的是具体实现者B的方法
abstraction.Operation()
}
3. 行为型模式(类或对象怎样交互以及怎样分配职责)
命令模式
将请求封装成一个对象,从而使得可以用不同的请求对客户端进行参数化
- 命令(Command):定义了执行操作的接口,通常包含一个执行方法。
- 具体命令(ConcreteCommand):实现了命令接口,持有接收者对象,并在执行方法中调用接收者的相应操作。
- 接收者(Receiver):负责执行具体的操作。
- 请求者/调用者(Invoker):持有命令对象,并在需要执行操作时调用命令对象的执行方法。
- 客户端(Client):创建命令对象、接收者对象和请求者对象,并进行它们之间的组装。
package main
import "fmt"
// 命令接口
type Command interface {
Execute()
}
// 具体命令A
type ConcreteCommandA struct {
receiver *Receiver
}
func (c *ConcreteCommandA) Execute() {
c.receiver.ActionA()
}
// 具体命令B
type ConcreteCommandB struct {
receiver *Receiver
}
func (c *ConcreteCommandB) Execute() {
c.receiver.ActionB()
}
// 接收者
type Receiver struct{}
func (r *Receiver) ActionA() {
fmt.Println("Receiver: Action A")
}
func (r *Receiver) ActionB() {
fmt.Println("Receiver: Action B")
}
// 请求者/调用者
type Invoker struct {
command Command
}
func (i *Invoker) SetCommand(command Command) {
i.command = command
}
func (i *Invoker) ExecuteCommand() {
i.command.Execute()
}
// 客户端代码
func main() {
// 创建接收者对象
receiver := &Receiver{}
// 创建具体命令A和B对象,并关联接收者
commandA := &ConcreteCommandA{receiver: receiver}
commandB := &ConcreteCommandB{receiver: receiver}
// 创建请求者对象,并设置命令A
invoker := &Invoker{}
invoker.SetCommand(commandA)
// 执行命令A
invoker.ExecuteCommand()
// 设置命令B
invoker.SetCommand(commandB)
// 执行命令B
invoker.ExecuteCommand()
}
策略模式
定义了一系列算法,并将每个算法封装在独立的类中,使得它们可以互相替换
- 策略接口(Strategy):定义了算法的公共接口,所有具体策略类都必须实现该接口。
- 具体策略(ConcreteStrategy):实现了策略接口,提供具体的算法实现。
- 环境类(Context):持有一个策略对象,并在需要执行算法时调用策略对象的方法。
package main
import "fmt"
// 策略接口
type Strategy interface {
Execute()
}
// 具体策略A
type ConcreteStrategyA struct{}
func (s *ConcreteStrategyA) Execute() {
fmt.Println("Executing strategy A")
}
// 具体策略B
type ConcreteStrategyB struct{}
func (s *ConcreteStrategyB) Execute() {
fmt.Println("Executing strategy B")
}
// 环境类
type Context struct {
strategy Strategy
}
func (c *Context) SetStrategy(strategy Strategy) {
c.strategy = strategy
}
func (c *Context) ExecuteStrategy() {
if c.strategy != nil {
c.strategy.Execute()
}
}
// 客户端代码
func main() {
// 创建具体策略A和策略B对象
strategyA := &ConcreteStrategyA{}
strategyB := &ConcreteStrategyB{}
// 创建环境对象
context := &Context{}
// 设置策略A,并执行策略
context.SetStrategy(strategyA)
context.ExecuteStrategy()
// 设置策略B,并执行策略
context.SetStrategy(strategyB)
context.ExecuteStrategy()
}
观察者模式
定义了一种一对多的依赖关系,使得当一个对象的状态发生变化时,它的所有依赖对象都会收到通知并自动更新
- 主题(Subject):也称为可观察者,它维护着一组观察者对象,提供注册、取消注册和通知观察者的方法。
- 观察者(Observer):定义了接收主题通知的接口,通常包含一个更新方法,用于在主题状态改变时更新自身。
- 具体主题(ConcreteSubject):实现了主题接口,维护着观察者对象的列表,并在状态改变时通知观察者。
- 具体观察者(ConcreteObserver):实现了观察者接口,通过注册到具体主题上,接收到主题通知时进行更新。
package main
import "fmt"
// 观察者接口
type Observer interface {
Update()
}
// 主题接口
type Subject interface {
Register(observer Observer)
Unregister(observer Observer)
Notify()
}
// 具体观察者A
type ConcreteObserverA struct{}
func (o *ConcreteObserverA) Update() {
fmt.Println("ConcreteObserverA: Received update")
}
// 具体观察者B
type ConcreteObserverB struct{}
func (o *ConcreteObserverB) Update() {
fmt.Println("ConcreteObserverB: Received update")
}
// 具体主题
type ConcreteSubject struct {
observers []Observer
}
func (s *ConcreteSubject) Register(observer Observer) {
s.observers = append(s.observers, observer)
}
func (s *ConcreteSubject) Unregister(observer Observer) {
for i, o := range s.observers {
if o == observer {
s.observers = append(s.observers[:i], s.observers[i+1:]...)
break
}
}
}
func (s *ConcreteSubject) Notify() {
for _, observer := range s.observers {
observer.Update()
}
}
// 客户端代码
func main() {
// 创建具体观察者A和B对象
observerA := &ConcreteObserverA{}
observerB := &ConcreteObserverB{}
// 创建具体主题对象
subject := &ConcreteSubject{}
// 注册观察者A和B到主题
subject.Register(observerA)
subject.Register(observerB)
// 发送通知给观察者
subject.Notify()
// 取消观察者B的注册
subject.Unregister(observerB)
// 再次发送通知给观察者
subject.Notify()
}