前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图解设计模式

图解设计模式

作者头像
用户1093396
发布2021-03-11 14:26:49
2450
发布2021-03-11 14:26:49
举报
代码语言:javascript
复制
本文不限于任何面向对象的编程语言

前言

常常听别人说设计模式不太容易理解,以及学习设计模式到底能帮我们解决什么问题,今天我们就用几张图来看看:

  • 设计模式到底是什么?
  • 为什么我们需要学习设计模式?

我也写过烂代码

是的,没什么,我也写过烂代码,刚毕业时业务逻辑也会一个函数干到底,只知道能实现功能就可以了。

代码语言:javascript
复制
package demo
 
func YourFunc() {
	// 所有的逻辑代码一股脑写完......
}

知道了拆分函数

自然而然知道了需要合理拆分函数。

然后把各个函数组织起来。

面临新的困境

某一天产品的需求需要支持新的场景,发现某一处的代码逻辑有变动需要支持新的场景,怎么办?

  1. 整个代码拷贝一份?不会有人这么干吧?(其实我还真见过,你们呢?)
  2. 把绿色变动的代码块,复制成一个新的函数,修改为新场景使用的函数?
  3. 把变动的代码再提为两个新函数,一个绿色为老代码,一个蓝色为新场景代码?

上面这种解决问题的方式就是面向过程的编程思想。

我们都在变优秀

随着我们不断的学习,学会使用了面向对象的特性。

以往函数式编程:

代码语言:javascript
复制
package demo
 
// 函数式编程
// 把一个个你以为可以独立的逻辑封住到一个函数里
func YourFunc() {
	// ......
}

面向对象编程:

代码语言:javascript
复制
package demo
 
// 面向对象编程
// 把不同的逻辑独立成一个对象
type DemoStruct struct{}
 
func (d *DemoStruct) YourFunc() {
	// ......
}

所以,我们如何用面向对象的思想组织上面的代码呢?

答案:继承。

学会了使用继承

代码语言:javascript
复制
特别备注:Go里面用合成复用

定义一个父类,并把差异业务代码抽象为一个抽象函数,其他代码逻辑都实现在父类。

不同的场景定义为不同的子类,子类继承父类,并实现抽象方法(也就是写差异代码)。

代码语言:javascript
复制
灰色:父类
绿色:场景一子类
蓝色:场景二子类

是不是很优雅的解决上面的场景的问题。

什么是设计模式?

优雅的解决上面场景问题时,利用面向对象特性的经验总结,就是设计模式。然而在历史的长河中,已经为我们总结了20+的常用设计模式,我们只需要学习和加以灵活运用即可。比如:

这!就是模板模式

还记得上面使用继承的过程吗?其实我们只需要做一件事情,就是经典的模板模式了,是什么?

答案:保证该场景下父类中封装的方法调用过程是稳定不变的,只是其中的方法可能变化。

代码语言:javascript
复制
灰色:父类
绿色:场景一子类
蓝色:场景二子类
黄色:场景三子类

这!就是策略模式

我们把上面代码做些改动:

  1. 不使用继承。
  2. 定义一个接口interface类型。
  3. 变更原抽象方法为调用一个接口interface类型的函数。
代码语言:javascript
复制
package demo
 
// DemoInterface 接口
type DemoInterface interface {
    DoSomething(ctx *Context) error 
}
 
var CurrentStrategyInstance DemoInterface
 
func Demo() {
	//.....逻辑略......
	CurrentStrategyInstance.DoSomething(c)
	//.....逻辑略......
}
代码语言:javascript
复制
灰色:主业务类
  1. 不同的场景定义为一个具体的类,且实现上面的interface。
代码语言:javascript
复制
灰色:主业务类
绿色:场景一DemoInterface的具体实现类
代码语言:javascript
复制
灰色:主业务类
绿色:场景一DemoInterface的具体实现类
蓝色:场景二DemoInterface的具体实现类
代码语言:javascript
复制
灰色:主业务类
绿色:场景一DemoInterface的具体实现类
蓝色:场景二DemoInterface的具体实现类
黄色:场景三DemoInterface的具体实现类
  1. 最后我们判断不同的场景初始化不同的具体类,再调用即可。

这!就是简单工厂模式 + 策略模式

接着我们把判断不同的场景初始化不同的具体类单独封装起来,这就是简单工厂模式 + 策略模式。

代码语言:javascript
复制
package demo
 
type DemoFactory struct {
}
 
// Get 获取实例
func (f *DemoFactory) Get(instanceType string) DemoInterface {
	switch instanceType {
	case "DemoA":
		return &DemoA{}
	case "DemoB":
		return &DemoB{}
	case "DemoC":
		return &DemoC{}
 
	default:
		panic("不支持的类型")
	}
}
 
// DemoInterface 接口
type DemoInterface interface {
    DoSomething(ctx *Context) error 
}
 
var CurrentStrategyInstance DemoInterface
 
func Demo() {
	//.....逻辑略......
  CurrentStrategyInstance = (DemoFactory{}).Get("DemoA")
	CurrentStrategyInstance.DoSomething(c)
	//.....逻辑略......
}
代码语言:javascript
复制
灰色(大):主业务类
灰色(小):简单工厂类
绿色:场景一DemoInterface的具体实现类
蓝色:场景二DemoInterface的具体实现类
黄色:场景三DemoInterface的具体实现类

这!就是状态模式

假设判断上面使用何种策略不是依赖外部,而是依赖内部状态,则我们调整下代码,则就变成了状态模式。

代码语言:javascript
复制
package demo

var currentStateInstance DemoInterface

func init() {
    // 定时器更新状态
    go func() {
        for {
            select {
            case t := <-time.NewTicker(1 * time.Second).C:
                // 模拟变成状态 StateA
                currentStateInstance = setState("StateA")
            }
        }
    }()
}
 
// Get 获取实例
func setState(State string) DemoInterface {
  // 变更状态
	switch State {
	case "StateA":
		return &StateA{}
	case "StateB":
		return &StateB{}
	case "StateC":
		return &StateC{}
 
	default:
		panic("不支持的状态")
	}
}

// DemoInterface 接口
type DemoInterface interface {
    DoSomething(ctx *Context) error 
}

// type StateA StateB StateC 略
 
// 模拟
func Demo() {
	//.....逻辑略......
	CurrentStateInstance.DoSomething(c)
	//.....逻辑略......
}
代码语言:javascript
复制
灰色(大):主业务类
灰色(小):修改内部状态的函数
绿色:场景一DemoInterface的具体实现类
蓝色:场景二DemoInterface的具体实现类
黄色:场景三DemoInterface的具体实现类

结语

举了这么多?,所以关于:

  • 设计模式到底是什么?
  • 为什么我们需要学习设计模式?

你有答案了吗?


本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-03-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 TIGERB的技术博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 我也写过烂代码
  • 知道了拆分函数
  • 面临新的困境
  • 我们都在变优秀
  • 学会了使用继承
  • 什么是设计模式?
    • 这!就是模板模式
      • 这!就是策略模式
      • 这!就是简单工厂模式 + 策略模式
      • 这!就是状态模式
      • 结语
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档