7.facade pattern
一.文档
https://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/facade.html
二.个人理解
facade模式,翻译为外观模式、门面模式,核心思想是屏蔽客户端对复杂系统的认识,通过facade将各个子系统进行整合,对外暴露简单的接口。
应用场景:复杂系统的简单化
三.角色分类
Facade 封装各个子系统
SubSystem 子系统类
package main
import (
"fmt"
"errors"
)
// 设备
// SubSystem 角色
type Equipment struct {}
// 检查设备是否正常
// 为简单化 只返回nil
func (e *Equipment) Check() error {
return nil
}
// 线路
// SubSystem 角色
type Circuit struct {}
// 检查线路是否正常
// 为简单化 只返回true
func (c *Circuit) Check() error {
return nil
}
// 开关
// SubSystem 角色
type Switch struct {
Status string
}
// 检查线路是否正常
// 为简单化 只返回true
func (s *Switch) Check() error {
switch s.Status {
case "ON":
return nil
case "OFF":
return errors.New("switch is off")
default:
return errors.New("switch unknow status")
}
}
// 值周 管理所有子系统
// facade角色
type OnDuty struct {
EquipmentSubSystem Equipment
CircuitSubSystem Circuit
SwitchSubSystem Switch
}
func (od *OnDuty) Check() {
if err := od.EquipmentSubSystem.Check(); err != nil {
fmt.Printf("OnDuty| check EquipmentSubSystem failed[%v].\n", err)
return
}
if err := od.CircuitSubSystem.Check(); err != nil {
fmt.Printf("OnDuty| check CircuitSubSystem failed[%v].\n", err)
return
}
if err := od.SwitchSubSystem.Check(); err != nil {
fmt.Printf("OnDuty| check SwitchSubSystem failed[%v].\n", err)
return
}
fmt.Printf("OnDuty| check all system success.\n")
return
}
func main() {
onDuty := OnDuty {
SwitchSubSystem : Switch {
Status : "OFF",
},
}
onDuty.Check()
}
7.flyweight pattern
一.文档
https://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/flyweight.html
二.个人理解
flyweight 模式,翻译为享元模式,核心思想是对类的创建并不总是重新生成,当某种类型的特性对象在内存中已经生成,则使用已有对象,对该对象进行共享,若内存中没有此对象则进行创建。目的就是为了减少内存消耗。
应用场景:对象创建频繁、且可共享使用,flyweight减少内存使用
三.角色分类
Flyweight 接口类,提供抽象的接口;抽象享元类,例子中为装备
ConcreteFlyweight 具体享元类,例子中为tank
FlyweightFactory 享元对象工厂
package main
import (
"fmt"
)
// 装备
// 抽象接口 Flyweight 角色
type Equipment interface {
Fire()
}
// 坦克
// 具体装备类 ConcreteFlyweight 角色
type Tank struct {
// 型号
Model string
}
func (t *Tank) Fire() {
fmt.Printf("Tank| model[%s] fire.\n", t.Model)
}
// 坦克工厂
// FlyweightFactory 角色
type TankFactory struct {
TankMap map[string]*Tank
}
// 获取坦克
// 非线程安全
func (tf* TankFactory) GetTank(model string) *Tank {
if tank, ok := tf.TankMap[model]; ok {
fmt.Printf("TankFactory| model[%s] tank already produced, return directly.\n", model)
return tank
}
fmt.Printf("TankFactory| model[%s] tank has not been produced, now produce it.\n", model)
tank := &Tank {
Model : model,
}
tf.TankMap[model] = tank
return tank
}
func main() {
tankFacory := TankFactory {
TankMap : make(map[string]*Tank),
}
tank := tankFacory.GetTank("tiger")
tank.Fire()
tank = tankFacory.GetTank("T-72")
tank.Fire()
tank = tankFacory.GetTank("T-72")
tank.Fire()
}
proxy pattern
一.文档
https://refactoring.guru/design-patterns/proxy
二.个人理解
proxy模式,翻译为代理模式,核心思想是对客户隐藏真实服务类,通过代理类完成被代理类的功能,且增加部分被代理类不具备的功能。客户端访问代理类,代理类可以直接替代被代理类进行工作,甚至可以屏蔽部分请求直接由代理类进行处理(例如网络防火墙、cache服务器,如果本地存在cache则直接返回而不是分发到后端服务器),甚至被代理类可以延迟初始化。
应用场景:
三.角色分类
subject 接口类,提供抽象的接口;类比服务接口
real subject 具体实现方法类,实现subject的各项接口;类比真实服务
proxy 代理。客户端真实交互对象,封装real subject功能,可以提供部分额外功能
package main
import (
"fmt"
)
// 金融服务接口
// subject 角色
type FinancialService interface {
// 理财
ManageMoney(money int)
}
// 前台
// proxy 角色
type FrontDesk struct {
manager Manager
}
// 理财
func (fd *FrontDesk) ManageMoney(money int) {
if money < 10000 {
fmt.Printf("FrontDesk| money[%d] less than 10000, buy a little finace products.\n", money)
return
}
fd.manager.ManageMoney(money)
}
// 验证资质
func (fd *FrontDesk) Auth(money int) bool {
if money <= 1000 {
fmt.Printf("FrontDesk| money[%d] less than 1000, can not been processed.\n", money)
return false
}
return true
}
// 经理
// 被代理类 real subject角色
type Manager struct {}
// 理财
func (m *Manager) ManageMoney(money int) {
fmt.Printf("Manager| put money[%d] into ivestment project.\n", money)
}
func main() {
frontDest := new(FrontDesk)
money := 100
if frontDest.Auth(money) {
frontDest.ManageMoney(money)
}
money = 2000
if frontDest.Auth(money) {
frontDest.ManageMoney(money)
}
money = 50000
if frontDest.Auth(money) {
frontDest.ManageMoney(money)
}
}
chain of responsibility
一.文档
http://wuxiaolong.me/2017/01/04/chainOfResponsibility/
二.个人理解
chain of responsibility pattern,翻译为责任链模式,核心思想是一个请求可能需要对应多个对象(这多个对象则形成了责任链)去进行处理,某个对象接手请求后会进行分析,若可以进行处理则内部进行处理,若处理不了可交由责任链上下一级的对象进行处理。
应用场景:请求处理流程、问题工单处理等流程化
三.角色分类
handler 接口类,提供处理请求的抽象接口、设置Next handler的接口;
concretehandler 具体实现方法类,实现handler的各项接口;
四.实例
学生犯事(根据情节使用1-10分来表示严重程度)首先交由老师进行处理,老师发现过于严重则交给校长,校长搞不定就交给公安局。
package main
import (
"fmt"
)
// 处理抽象接口
type handler interface {
Process(score int)
SetNextHandler(handler)
}
// 警察 实现处理抽象接口
type police struct {
nextHandler handler
}
// 校长 实现处理抽象接口
type rector struct {
nextHandler handler
}
// 教师 实现处理抽象接口
type teacher struct {
nextHandler handler
}
// 警察处理问题少年
func (p *police) Process(score int) {
if score > 5 && score <= 10 {
fmt.Printf("police| score[%d] been processed by police.\n", score)
} else {
if p.nextHandler != nil {
p.nextHandler.Process(score)
} else {
fmt.Printf("police| score[%d] can not been processed by police, and police has no next handler, process failed.\n", score)
}
}
}
// 警察设置调用链下一级处理者
func (p *police) SetNextHandler(h handler) {
p.nextHandler = h
}
// 校长处理问题少年
func (r *rector) Process(score int) {
if score > 3 && score <= 5 {
fmt.Printf("rector| score[%d] been processed by rector.\n", score)
} else {
if r.nextHandler != nil {
r.nextHandler.Process(score)
} else {
fmt.Printf("rector| score[%d] can not been processed by police, and rector has no next handler, process failed.\n", score)
}
}
}
// 校长设置调用链下一级处理者
func (r *rector) SetNextHandler(h handler) {
r.nextHandler = h
}
// 教师处理问题少年
func (t *teacher) Process(score int) {
if score > 0 && score <= 3 {
fmt.Printf("teacher| score[%d] been processed by teacher.\n", score)
} else {
if t.nextHandler != nil {
t.nextHandler.Process(score)
} else {
fmt.Printf("teacher| score[%d] can not been processed by police, and teacher has no next handler, process failed.\n", score)
}
}
}
// 教师设置调用链下一级处理者
func (t *teacher) SetNextHandler(h handler) {
t.nextHandler = h
}
func main() {
policeAlice := new(police)
policeAlice.SetNextHandler(nil)
rectorBob := new(rector)
rectorBob.SetNextHandler(policeAlice)
teacherCindy := new(teacher)
teacherCindy.SetNextHandler(rectorBob)
// 处理2分问题少年
teacherCindy.Process(2)
// 处理5分问题少年
teacherCindy.Process(5)
// 处理8分问题少年
teacherCindy.Process(8)
// 处理12分问题少年
teacherCindy.Process(12)
}
command pattern
一.文档
https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/command.html
二.模式理解
command pattern模式,翻译为命令模式,也叫事件驱动模式。将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式。
应用场景:要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活。命令模式可以对发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。这就是命令模式的模式动机。
三.角色分类
我们以遥控赛车为例子,人通过遥控器来遥控赛车启动、停止、前进、后退等功能,按动启动、停止就是生成command,其中遥控器就是invoker 真正去执行命令,receiver就是被遥控的赛车。
command 接口类,提供抽象的接口;
concretecommand 具体实现方法类,实现command的各项接口;类比停止命令
invoker 命令调用类,向recevier发送命令;
recevier 命令接收类,接收外部请求 并执行命令
package main
import (
"fmt"
"container/list"
)
// 命令类型
/***********************************
const (
Start = 1 // 启动
Stop = 2 // 停止
Forward = 3 // 前进 每次前进1m
Back = 4 // 后退 每次后退1m
Echo = 5 // 显示赛车位置 注意赛车的移动路径只有一维,前进或者后退
)
***********************************/
// 命令抽象接口
type command interface {
// 执行命令
Action()
}
// concentrete comand 启动命令
type commandStart struct {
Car *revolt
}
// concentrete comand 停止命令
type commandStop struct {
Car *revolt
}
// concentrete comand 前进命令
type commandForward struct {
Car *revolt
}
// concentrete comand 后退命令
type commandBack struct {
Car *revolt
}
// concentrete comand 显示位置命令
type commandEcho struct {
Car *revolt
}
// recevier 接收命令类
// 遥控赛车
type revolt struct {
location int
}
// invoker 遥控器
type remoteControl struct {
// 命令history 可通过此扩展undo、redo等操作
commandList *list.List
}
func (cs *commandStop) Action() {
cs.Car.Stop()
}
func (cs *commandStart) Action() {
cs.Car.Start()
}
func (cb *commandBack) Action() {
cb.Car.Back()
}
func (cf *commandForward) Action() {
cf.Car.Forward()
}
func (ce *commandEcho) Action() {
ce.Car.Echo()
}
func (r *revolt) Start() {
fmt.Printf("revolt| start the engine.\n")
}
func (r *revolt) Stop() {
fmt.Printf("revolt| stop the engine.\n")
}
func (r *revolt) Back() {
r.location = r.location - 1
fmt.Printf("revolt| go back one meter, now location[%d].\n", r.location)
}
func (r *revolt) Forward() {
r.location = r.location + 1
fmt.Printf("revolt| go forward one meter, now location[%d]\n", r.location)
}
func (r *revolt) Echo() {
fmt.Printf("revolt| echo location[%d].\n", r.location)
}
// 初始化命令列表
func (rc *remoteControl) Init() {
if rc.commandList == nil {
rc.commandList = list.New()
}
return
}
// 存储命令
func (rc *remoteControl) StoreCommand(c command) {
rc.commandList.PushBack(c)
}
// 执行命令
func (rc *remoteControl) ExecuteCommands() {
for e := rc.commandList.Front(); e != nil; e = e.Next() {
e.Value.(command).Action()
}
}
// 清理命令
func (rc *remoteControl) ClearCommands() {
rc.commandList.Init()
}
func main() {
// 生成对应实例
car := new(revolt)
start := new(commandStart)
start.Car = car
stop := new(commandStop)
stop.Car = car
forward := new(commandForward)
forward.Car = car
back := new(commandBack)
back.Car = car
echo := new(commandEcho)
echo.Car = car
controler := new(remoteControl)
controler.Init()
// 执行命令
// 启动、前进、打印位置、停止
controler.StoreCommand(start)
controler.StoreCommand(forward)
controler.StoreCommand(echo)
controler.StoreCommand(stop)
controler.ExecuteCommands()
controler.ClearCommands()
// 执行命令
// 启动、前进、前进、前进、后退、打印位置、停止
controler.StoreCommand(start)
controler.StoreCommand(forward)
controler.StoreCommand(forward)
controler.StoreCommand(forward)
controler.StoreCommand(back)
controler.StoreCommand(echo)
controler.StoreCommand(stop)
controler.ExecuteCommands()
controler.ClearCommands()
}