研磨设计模式_设计模式,费尽心力吐槽你

     程序猿,没有不知道设计模式的,但是很少有人拍着胸脯说:“I Got It ”。我从第一次面试起,就被challenge,你知道哪些设计模式?用过哪些?能说说它的原理吗?(但凡阿里面试,都会问,哈哈,我一般也会回问,你们平常用得到吗?)

    设计模式,我已经看了三年了,《Design Pattern》看了30页(不推荐大家看了,这是本强者称奇,弱者骂娘的神书),《研磨设计模式》看了三遍,希望结合自己的感悟,对其做一番总结吧!

   注1:在写总结时,偶然发现https://refactoringguru.cn/design-patterns这个神奇的网站,推荐给大家!!!

1 设计模式鸟瞰图

4a24171950102c6fba899459077c48e3.png

1.1 分类标准

  • 创建型模式:提供创建对象的机制,增加已有代码的灵活性和可复用性

  • 结构型模式:介绍如何将对象和类组装成较大的结构,并同时保持结构的灵活和高效

  • 行为模式:负责对象间的高效沟通和职责委派

1.2 厂公的过去式

工厂模式的知名度,和单例模式并驾齐驱,在之前的《设计模式之工厂三剑客》中已经介绍过,在此不做赘述。作为一个gopher,只想多说一句,工厂方法不适合golang。

1.3 放弃的你:不是你不够好,是我爱不起

  • 原型模式:该模式在前端(Javascript)中很重要,其本质是“克隆生成对象”,做数据拷贝之用。

  • 享元模式:名字很唬人,其实就是多个对象使用相同的数据对象作为其属性,为了减少内存占用,将共用的数据对象以引用的方式使用。(个人困惑:这其实不就是指针引用吗?)

  • 命令模式:你知道就好

  • 解释器模式:自说自话,定义一种文法,定义一个解释器去读懂它!说实话,它很重要,比如golang的spf13/pflag就承担解释器的角色。只可惜,这种底层的轮子,我们不会去造,也造不来。

  • 备忘录模式:对象的备忘录,就是对象的字段属性的拷贝另存,只不过基于业务场景,可能只保存部分字段属性。

1.4 国之重“器”

生成器适配器装饰器迭代器解释器
定义将一个复杂对象的构建与它的表示分离,是的同样的构建过程可以创建不同的表示将一个类的接口转换为客户希望的另外一个接口。动态地给一个对象添加一些额外的职责(功能)提供一种方法顺序访问一个聚合对象中的各个元素,而不需要暴露该对象的内部表示给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
目的用于构建复杂的产品,而且是细化的、分步骤的构建产品适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以其一工作。动态地为对象增加功能提供对聚合对象的迭代访问使用解释器对象来表示和处理相应的语法规则
本质分离整体构建算法和部件构造转换匹配,复用功能动态组合控制访问聚合对象中的元素分离实现,解释执行

1.5 行者模式

中介者观察者访问者
定义用一个中介对象来封装一系列对象的交互定义对象间的一种一对多的依赖关系。当一个对象的状态发生变化时,所有依赖于它的对象都能得到通知并被自动更新表示一个作用域某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下,定义作用于这些元素的新操作
目的统一管理一组关联对象,彼此之间不显示调用,使其耦合松散统一管理依赖关系,建立联动机制动态扩展已有类的功能
本质封装交互触发联动预留通路,回调实现

1.6 “链”式结构

75b772c3cfbf0a1ecf6d153f99cd54b6.png

2 重点关注

2.1 单例模式:最简单,送分题

type DeployManager struct {  TaskChan chan DeployTask  Engine   *options.Engine}var manager *DeployManagerconst size=1000func GetDeployManager(engine *options.Engine) *DeployManager {  if manager == nil {    manager = &DeployManager{      TaskChan: make(chan DeployTask, size),      Engine:   engine,    }  }  return manager}

2.2 桥接模式:维度的划分与融合

2.2.1 功能代码

package bridgeimport "fmt"type printer interface {  print()}type Mac struct {  printer printer}func (m *Mac) setPrinter(p printer) {  m.printer = p}func (m *Mac) print() {  fmt.Print("Mac 打印,")  m.printer.print()}type Windows struct {  printer printer}func (w *Windows) setPrinter(p printer) {  w.printer =p}func (w *Windows) print() {  fmt.Print("Windows 打印,")  w.printer.print()}type HPPrinter struct {}func (h *HPPrinter) print() {  fmt.Println("惠普打印机!")}type CannonPrinter struct{}func (c *CannonPrinter) print() {  fmt.Println("佳能打印机!")}

2.2.2 测试代码

package bridgeimport "testing"func TestBridge(t *testing.T) {  mac := new(Mac)  win := new(Windows)  hp := new(HPPrinter)  cannon := new(CannonPrinter)  mac.setPrinter(hp)  mac.print()  mac.setPrinter(cannon)  mac.print()  win.setPrinter(hp)  win.print()  win.setPrinter(cannon)  win.print()}

114468ba4dedb273408e2e4f17633cdb.png

2.2.3 桥接模式讲解

与其说桥接模式的本质是“分离抽象和实现”,倒不如说是“维度切割”,以最小、最恰当的粒度自由组合!在发布系统中,发布介质有“容器、虚拟机”,发布模式有“滚动发布、蓝绿发布、灰度发布”,二者逻辑组合有六种方式,采用桥接模式,可以清晰权责,避免代码混乱融合!(让专业的人,做专业的事!)

0f39e3e02f114461bcee84a0cc03f373.png

2.3 装饰器模式:我最爱问你

只要你说你会python,我是一定会问装饰器的。前文已经讲过装饰器了,它在python中的@语法糖,让你可以轻松使用装饰器。

@a_new_decoratordef a_function_requiring_decoration():    """Hey you! Decorate me!"""    print("I am the function which needs some decoration to "          "remove my foul smell") a_function_requiring_decoration()#outputs: I am doing some boring work before executing a_func()#         I am the function which needs some decoration to remove my foul smell#         I am doing some boring work after executing a_func() #the @a_new_decorator is just a short way of saying:a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)

设计模式,是一种思维方式,并不拘泥于形式和语言。在golang中,我们通常借助于defer来做装饰器:

func (f *Filter) StaticFuncCost(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {  start := time.Now()  defer func() {    cost := fmt.Sprint(time.Since(start).Milliseconds())    logs.Info("Request:", req.Attribute(cv.RequestID), ",开始时间:", timeconv.Format(start), ",总耗时:", cost, "ms")  }()  chain.ProcessFilter(req, resp)}

装饰器有什么好处?AOP,面向切面编程,做一些与业务逻辑无关的专项功能,如日志、安全、性能统计等等!

2.4 观察者模式:Observer与Watcher

2.4.1 基础知识

6af50cf86c6efd14e1be76c2b92733fb.png

2.4.2 结构图

b0821bcec1cee53d8f35fafedbafcd53.png

2.4.3 时序图

26cd03dd3b9569e11db7a7a17bb0712e.png

2.4.4 Show Me Code

应用部署器,部署后需要通知Tester自动化测试、Securitier做安全扫描、通知研发做部署验证。

package observerimport "fmt"type Observer interface {  update(string)  getID() string}type Subject interface {  register(obs Observer)  deregister(obs Observer)  notifyAll()}type Deployer struct {  DeployId string  ObserverMap map[string]Observer}func (d *Deployer) register(obs Observer) {  d.ObserverMap[obs.getID()] = obs}func (d *Deployer) deregister(obs Observer) {  delete(d.ObserverMap, obs.getID())}func (d *Deployer) notifyAll() {  for _, obs := range d.ObserverMap{    obs.update(d.DeployId)  }}func NewDeployer(id string) *Deployer {  return &Deployer{    DeployId: id,    ObserverMap: map[string]Observer{},  }}type Tester struct {  id string}func (t *Tester) getID() string {  return t.id}func (t *Tester) update(d string) {  fmt.Printf("部署(ID:%s)完成,开始执行测试任务:%s\n", d, t.id)}type Securitier struct{  id string}func (t *Securitier) getID() string {  return t.id}func (t *Securitier) update(d string) {  fmt.Printf("部署(ID:%s)完成,开始执行安全扫描任务:%s\n", d, t.id)}type Developers struct {  id string}func (t *Developers) getID() string {  return t.id}func (t *Developers) update(d string) {  fmt.Printf("部署(ID:%s)完成,请%s研发组同学验证\n", d, t.id)}

业务功能都不是孤立的,必有其上下游,观察者模式通过观察注册的方式集中管理起来,避免硬编码联动关系,松散耦合,也让代码更专注于其本身的业务逻辑!

2.5 访问者模式:来自K8S的爱

K8S代码里大规模的使用Visitor,在我看来visitor是将个性化、定制化的功能交给使用者,作为visitor服务商只需要做最底层的基础的服务功能,通常这类功能是单一的。

// URLVisitor downloads the contents of a URL, and if successful, returns// an info object representing the downloaded object.type URLVisitor struct {  URL *url.URL  *StreamVisitor  HttpAttemptCount int}func (v *URLVisitor) Visit(fn VisitorFunc) error {  body, err := readHttpWithRetries(httpgetImpl, time.Second, v.URL.String(), v.HttpAttemptCount)  if err != nil {    return err  }  defer body.Close()  v.StreamVisitor.Reader = body  return v.StreamVisitor.Visit(fn)}

参考文献:https://cloud.tencent.com/developer/article/1052415

2f4c809fd77fb64b7556a925f225c302.png

3 我心憔悴,如何慰藉

23种设计模式,看完了,也就忘完了!我辈该如何?

3.1 说文解字:识名,解意,不必苛求结构

好的命名,其义自见,无需过多解释;对于设计模式的类结构关系,也未必要完全遵守,把握其灵魂即可。

3.2 目的,目的,目的,只有知其为何,才能够何为!

学习设计模式,经常会被设计模式的结构绕来绕去就绕晕了。其实,以目的为导向,知道该模式是解决什么问题,怎么做会最好。因此,无需背诵枯燥的记忆,带着问题、带着场景即可学会!

3.3 实践出真知,将设计模式套入你的功能场景中

看懂了,不是真的懂,要能自己写出来,要将设计模式应用到日常的功能开发与系统设计中,只有用,才能真正体味其原理和思想。

3.4 设计模式是思维,是太极,重意、不重形

初级阶段,要照葫芦画瓢,学习设计模式的结构;高级阶段,要掌握其思想和灵魂,这样就可以根据场景合理的设计结构,并非生搬硬套。

3.5 设计模式本质一览图

c59dc1c1cb7736395215f6f957aa6d10.png

内容简介 · · · · · · 《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,培养正确的“设计观”;中高级内容则深入探讨如何理解这些模式,包括模式中蕴涵什么样的设计思想,模式的本质是什么,模式如何结合实际应用,模式的优缺点以及与其他模式的关系等,以期让读者尽量去理解和掌握每个设计模式的精髓所在。 《研磨设计模式》在内容上深入、技术上实用、和实际开发结合程度很高,书中大部分的示例程序都是从实际项目中简化而来,因此很多例子都可以直接拿到实际项目中使用。如果你想要深入透彻地理解和掌握设计模式,并期望能真正把设计模式应用到项目中去,那么这是你不可错过的一本好书。 《研磨设计模式》难度为初级到中级,适合与所有开发人员、设计人员或者即将成为开发人员的朋友。也可以作为高效学生深入学习设计模式的参考读物! 作者简介 · · · · · · 陈臣:十年Java/JavaEE开发经验,高级系统架构师,功力深厚,技术精湛,精通Java/JavaEE相关技术和多种开源框架,尤其擅长系统分析和架构设计。从事过专业的中间件研发,包括基于组件的Web页面框架、基于WFMC的工作流中间件、类似于Hibernate的ORM框架等等;参与或主持了多个中大型的企业级应用项目,拥有多年项目经理、技术部经理的管理经验。个人博客:http://www.javass.cn/javapeixunxxyd/index.html 王斌:从事Java/JavaEE开发五年,系统架构师,精通Ejb、Struts、Spring、Hibernate、iBatis等框架技术,擅长设计模式和Eclipse插件开发。作为架构小组骨干,参与了国旅电子商务平台、南王酒庄等多个项目的开发,开发并维护有constance4j、myxstream、SimpleMapping等多个公司内部开源框架,深得多个项目组好评。
本电子书一共两个压缩文档,该文档为part1。 《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,培养正确的“设计观”;中高级内容则深入探讨如何理解这些模式,包括模式中蕴涵什么样的设计思想,模式的本质是什么,模式如何结合实际应用,模式的优缺点以及与其他模式的关系等,以期让读者尽量去理解和掌握每个设计模式的精髓所在。    《研磨设计模式》在内容上深入、技术上实用、和实际开发结合程度很高,书中大部分的示例程序都是从实际项目中简化而来,因此很多例子都可以直接拿到实际项目中使用。如果你想要深入透彻地理解和掌握设计模式,并期望能真正把设计模式应用到项目中去,那么这是你不可错过的一本好书。 《研磨设计模式》难度为初级到中级,适合与所有开发人员、设计人员或者即将成为开发人员的朋友。也可以作为高效学生深入学习设计模式的参考读物! 第1章 设计模式基础    第2章 简单工厂    第3章 外观模式    第4章 适配器模式(Adapter)    第5章 单例模式(Singleton)    第6章 工厂方法模式(Factory Method)    第7章 抽象工厂模式(Abstract Factory)    第8章 生成器模式(Builder)    第9章 原型模式(Prototype)    第10章 中介者模式(Mediator)    第11章 代理模式(Proxy)    第12章 观察者模式(Observer)    第13章 命令模式(Command)    第14章 迭代器模式(Iterator)    第15章 组合模式(Composite)    第16章 模板方法模式(Template Method)    第17章 策略模式(Strategy)    第18章 状态模式(State)    第19章 备忘录模式(Memento)    第20章 享元模式(Flyweight)    第21章 解释器模式(Interpreter)    第22章 装饰模式(Decorator)    第23章 职责链模式(Chain of Responsibility)    第24章 桥接模式(Bridge)    第25章 访问者模式(Visitor)    附录A常见面向对象设计原则    附录BUML简介    参考文献
本电子书一共两个压缩文档,本文件为part2. 《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,培养正确的“设计观”;中高级内容则深入探讨如何理解这些模式,包括模式中蕴涵什么样的设计思想,模式的本质是什么,模式如何结合实际应用,模式的优缺点以及与其他模式的关系等,以期让读者尽量去理解和掌握每个设计模式的精髓所在。    《研磨设计模式》在内容上深入、技术上实用、和实际开发结合程度很高,书中大部分的示例程序都是从实际项目中简化而来,因此很多例子都可以直接拿到实际项目中使用。如果你想要深入透彻地理解和掌握设计模式,并期望能真正把设计模式应用到项目中去,那么这是你不可错过的一本好书。    《研磨设计模式》难度为初级到中级,适合与所有开发人员、设计人员或者即将成为开发人员的朋友。也可以作为高效学生深入学习设计模式的参考读物! 第1章 设计模式基础    第2章 简单工厂    第3章 外观模式    第4章 适配器模式(Adapter)    第5章 单例模式(Singleton)    第6章 工厂方法模式(Factory Method)    第7章 抽象工厂模式(Abstract Factory)    第8章 生成器模式(Builder)    第9章 原型模式(Prototype)    第10章 中介者模式(Mediator)    第11章 代理模式(Proxy)    第12章 观察者模式(Observer)    第13章 命令模式(Command)    第14章 迭代器模式(Iterator)    第15章 组合模式(Composite)    第16章 模板方法模式(Template Method)    第17章 策略模式(Strategy)    第18章 状态模式(State)    第19章 备忘录模式(Memento)    第20章 享元模式(Flyweight)    第21章 解释器模式(Interpreter)    第22章 装饰模式(Decorator)    第23章 职责链模式(Chain of Responsibility)    第24章 桥接模式(Bridge)    第25章 访问者模式(Visitor)    附录A常见面向对象设计原则    附录BUML简介    参考文献
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值