设计模式(三)

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()
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值