一文搞懂23种设计模式, 再不会来找我

本人对设计模式的看法

曾几何时, 我钻研了无数遍设计模式, 每次感觉好像自己明白了, 一到写代码就GG了; 明明是很高深的武林秘籍啊, 怎么关键时刻就使用不出来呢?

我越来越觉得自己的学习方法有问题, 于是我把自己以前的学习思路想了一遍, 发现了一个重要的问题; 那就是每次学习设计模式都是按照书上或者博文里告诉你这个设计模式是干啥的? 这个设计模式能用在哪? 而这些条条框框根本不受用, 原因就在于不明白设计模式的原理, 生搬硬套是不行的。

举个例子啊, 就好像高中时候学数学一样, 直接告诉你一个柯西不等式, 你会用吗? 而如果是一步步推导出来, 你是不是对他印象更新呢? 世界上的知识太多了, 如果抓不住本源的东西, 想把他们都学会, 脉络都没有, 怎么学呢?

新的设计模式学习方法

因此, 我自己研究了新的设计模式学习方法, 就是以面向对象的三大特性 + 六大设计原则, 指导我们把代码写好; 好了, 现在先不用想那23种或者多少种设计模式; 就看这些基本的特性和原则:

三大特性

  1. 封装是为了封装"不变", 我们只要区分开"变与不变"就可以了, 比如这个方法经常被调用, 调用他的地方有好几十处, 封装一下是不是就少了很多冗余的代码
  2. 继承是类结构上的封装, 比如猫类, 狗类都能跑, 能跳, 能吃, 能睡, 可以不可以提取出来放到父类里, 而他们特有的就可以放在他们各自的类中
  3. 多态本身是针对父子类的一种使用上的便利, 这里暂时先不关注

六大原则

  1. 单一职责原则: 一句话, “类要尽可能小巧”(当前也包括方法), 注意这里我用的是"小巧"而不是"小", 过度的小也没什么好处; 怎么界定呢, 就是发生变化的基本单位 + 自然界中的整体, 如果说要抽象的这个类不是自然界中的就按单个变化起手, 如果是自然界的就按照自然界的; 比如人是个单独的类, 鸡是个单独的类; 开锁是个单独的接口, 灯的光控和声控是两个接口; 听到这里应该明白了吧
  2. 开闭原则: “对扩展开放, 对修改关闭”, 就是你写好的完备的类, 尽量别改了, 需要改啊想办法新定义类把功能嫁接上去; 至于怎么弄, 后面慢慢说
  3. 里氏替换原则: 子类可以替代父类, 意思就是子类不能改父类的东西; 这让我想起了论语里的一句话子曰:“父在,观其志,父没观其行,三年无改于父之道,可谓孝矣。”, 就是说你不能老是想着造你爸的反, 因为你爸代表你们这个家, 代表你; 如果他代表不了你了, 那不就乱了; 和写代码一个道理, 本来继承和多态用起来多好, 规矩森严, 就像家族中的的父与子;
  4. 接口隔离原则: 这个自我感觉和单一职责差不多, 放一块理解行了(有的时候就不能太死板, 明白啥意思行了, 学知识别太紧张)
  5. 迪米特原则: 说的是类和类之间少点纠缠, 别谁离了谁活不了似的; 这说明什么问题? 第一, 如果已经按照单一职责在做了, 纠缠的概率绝对小, 为什么呢? 你如果需要另一个类的东西说明你离不开他啊! 你得考虑考虑是不是这俩本来放在一个类里比较好呢? 第二点就是我只关系我需要的, 比如我需要一个挖掘机, 你把挖掘机给我行了, 别把轮子, 挠子分开给我, 告诉我这就是个挖掘机自己组装去吧; 这其实是封装的东西, 该封装的封装一下啊
  6. 依赖倒置原则: 能抽象的尽量抽象出来(因为这样就很清爽), 这点和迪米特法则有一部分想通, 综合理解一下

好了"三大特性"和"六大原则"介绍完了, 3+6=9, 9这个数字在中国意义非凡, 有句话就是九九归一, 感觉已经掌握了全部的精髓了呢!

逐个分析23种设计模式

首先声明一点啊, 下面的讲解没有具体的类图和代码, 我不太喜欢那样写博客, 确实很累; 而且我感觉不需要, 看类图对我而言就一个字"烦", 根本看不明白怎么回事(不要笑我菜啊, 嘻嘻).

好了, 了解过设计模式的都知道这些设计模式分为几大类? 创建型模式, 结构型模式, 行为型模式

创建型模式

先把创建型模式讲了, 创建型模式就是指导我们怎么创建对象的, 有人说创建对象我会啊new Person()就是个人, new Animal()就是个动物; 对啊没毛病, 如果是new 飞机(), new 火箭(), new 马斯克()(幽默一下)呢? 飞机零部件多啊, 也就是什么? 属性多啊, 那构造函数的参数列表不得满屏啊(一行完了换一行); 怎么办呢? 又有小机灵鬼说用set啊, 先new一个空对象, 然后挨个set; 你就说set的你烦不烦吧! 你肯定问我了咋办, 要不咱用用建造者模式, 这里有一个问题啊, 就是好多人觉得直接set和用建造者模式没区别啊, 对从代码量上可能区别不是很大, 大家看看人家叫什么名字:“建造者模式”, 盖一座房, 先干什么再干什么(先打地基, 然后xxx), 区别就区别在这了, 你哐哐set的那玩意有先后顺序吗? 有建造的灵魂吗? 有些人肯定觉得我是在强词夺理; 好吧, 举个例子啊: 还是拿飞机举例子吧, 如果说我创建一个飞机怎么创建, 先创建驾驶舱, 再创建机翼, 等等等等, 这些每个可以单独写一个builder类, 是的你没听错, 是单独写一个builder类; 如果是用set呢, 把所有的属性先对照着set1, set2, set3, set4; 好不对照呢, 能set出来吗? 当前之前看网上还有一种说法, 就是builder可以在最后的build方法里加一些参数的综合校验, set不行, 倒是也对, 但我觉得不是重点!

上面已经省了点事了, 给分开了, 还有更省事的, 我看人家的飞机和我这个飞机差不多啊, 我复制一个好不好; copy懂吧(CV大法), 我不说大家也知道是什么模式了吧!

创建一个对象已经很方便了, 那如果创建多个对象呢? 小聪明又出来了, 创建一个和创建多个没区别啊和上面一样啊, 如果是根据不同情况创建的对象不一样呢? 还是有小聪明说了, 这个我会if -> else if -> else; 还有的说我会用switch; 能用倒是能用, 上面的原则还记得吗? 小伙伴们都蒙了, 你上面讲的什么来着, "开闭原则"啊, “迪米特原则"啊, 你如果细琢磨好多原则都不建议你这么做, 因为他都在告诉你一件事, 让你分出"变与不变”, 不变的是什么? 初心不变啊, 我TM要创建对象啊, 怎么让我干这么多事啊, 宝宝不开心! 把创建对象的过程封装一下吧(工厂模式就是这个, 抽象工厂也不单独展开了, 差不多意思)

最后讲一下单例模式, 有些东西只要有一个就够了, 比如"天", “道”, 总有一些要掌握全局的吧! 多的就不说了, 从理论上你们知道的比我多.

结构型模式

下面分开来说一下啊! 咳咳

适配器模式装饰者模式都是干同一个事, 往已有的类上加东西呗(为什么加东西, 开闭原则啊), 就是方式方法不同, 我也不打算展开了, 道理明白了就行呗; 非得展开讲讲? 以后吧

包括代理模式, 有个类代理你这个类, 帮你做点你做不了的事, 比如中介; 中介帮你和房东谈谈价格; 在我看来和上述的那两个也是一个玩意, 再提醒一句啊, 形式不重要, 哪怕你不知道咋回事, 你一想到这个类得加点东西, 装饰者模式就是相当于套壳子, 适配器模式就相当于借助外来的力量, 代理模式就是退居幕后了, 和适配器模式不同的是, 虽然借助适配器的力量, 但还是咱说了算啊(方法走的咱的), 代理是彻底交给别人了, 爱咋咋地吧!

还有外观模式, 我自认为和"代理模式"没区别, 其实在我看来这几个都没区别! 如果非要说区别, 区别就是"外观模式"就是吕不韦, 门客众多, 但是发布的书叫"吕氏春秋", "代理模式"是代理你, 为你服务的; "外观模式"是告诉你规矩, 让你在人家手底下干的, 服从人家的;

桥接模式, 我都不想说了, 网上有些说是优化"多重继承"问题的, 有点扯, 还"多重继承", 如果是上来就按照六大原则做系统, 根本都没有"桥接"什么事, 本来就是最小原则了, 还最少依赖了, 那不本身就是桥接的吗? 为什么会有这个设计模式呢? 是因为, 上来写代码写的没有那么优美, 那么规范, 然后想改改代码啊, 或者优化重构的时候, 发现一大坨类, 好了优化优化吧! 听结论啊, 就按照原则走, 这个模式不用记他.

下面说组合模式, 组合模式场景比较特定啊, 比如"文件夹"啊, 目录树啊; 就是把一群和一个能统一表示吗? 这样就不用关心下一层是一群还是一个了, 应用于层级机构场景比较固定, 不展开了

享元模式也是场景化的东西, 比如"连接池"啊之类的, 就是开发项目的过程中发现的这些问题, 总结了一个设计模式, 不用记, 因为到了用到他的场景, 比如你开发个连接池, 你不知道用的是他也是他了

行为型模式

首先说一下, 什么叫做"行为型模式", 就是"你对我做了什么?", “你怎么对我做的这些, 用的什么方式方法”!

策略模式, 曾经这个模式困扰我很久, 啥叫"策略模式"啊, 什么策略啊, 看着好像跟继承封装没区别啊, 也是父类和子类啊, 对就是没区别; 为什么叫"策略模式", 就是因为方法里都是各种各样的策略, 然后是各种各样的策略类; 就是从实际场景出发的呀, 结论: 鸟都不用鸟

下面是模版方法模式, 这个也不用管了, 这就是继承封装, 把方法步骤封装到父类, 就告诉你你只能这么做, 别瞎整; 还是那句话, 区分"变与不变", 变的是"每一步怎么做", 不变的是这些步骤, 爱叫什么模式什么模式

观察者模式, 这个是针对场景的, 比较固定, 不展开了

迭代器模式, 也是针对场景的, 不展开了, 继续絮叨一句, 针对场景的也不用记, 因为你解决那个场景的问题, 自然用的就是这个

责任链模式, 也是针对场景的, 补充一句, 大家可以会直接认为凡是需要多个步骤的任务可以使用"责任链模式", 我直接说一点, 模版方法弄出来的直接就能转"责任链模式", 要不要转呢? 有侧重点奥, 模版方法基本上步骤就固定了, 责任链这些链比较灵活, 实现上肯定能互相转换; 具体看业务情况.

命令模式, 也是继承封装, 唯一的区别是不是那种业务上的人性的封装, 按照业务走你不可能封装成命令; 还是针对特定场景的, 比如能发送命令, 还能撤销命令, 我的观点是忽略, 基本用不到; 如果用到了也是有这样的需求: 开发个xxx系统, 能下发命令, 还能撤销命令; 好了, 你就算不知道这个模式, 也是这么个做法吧

备忘录模式, 也是特定场景, 比如"事务回滚"啊, "游戏存档"啊, 不用记

状态模式, 就是"策略模式", 他俩你弄混了都不要紧, 不影响你继承封装, pass

访问者模式, 这个有点特殊啊, 我之前最早研究设计模式的时候, 就这个最懵; 要不别说了? 哈哈, 开玩笑的; 之前我记得网上说的最多的就是"它能将操作与其所作用的对象隔离开来。“; 哈哈, 这不都是废话吗? 那都分开吧, 都用这种模式吧! 如果你说将操作与对象隔开好, 那怎么不都隔开呢? 你听我的, 第一这个玩意场景也很少就那几个"AST树遍历啊”, 还有就是"编译器语法解析啊"; 第二如果你真想用它, 什么时候? 举个例子啊: 你如果要在父类增加一个方法, 并且实现类都有个性化的实现, 怎么办, 有几个实现类加几个呗? 没毛病, 那如果是好几十个实现类呢, 小聪明又来了, 挨个加呗! 恭喜你, 没问题, 针没问题; 那要是嫌累不想加呢? 这个模式就能满足你啊, 定义两个类, 一个Visitor抽象类, 一个具体的Visitor, 里面有针对每个实现类的单独方法; 我直接总结一下吧, 就是"用纵向的换横向的"; 什么? 你觉得我说的没道理啊! 好吧, 你按照自己来也行, 毕竟我也是一家之言啊!

中介者模式, 最上面不是说过吗, 行为型模式就是"你对我做的这些, 用的什么方式方法", 答: 通过中介者的方式; 这是一个星状结构, 所有人连接在中介者上面, 中介维护的有所有人的列表, 每个人将消息发送给中介者; 大家一看就能联想到C/S架构吧, 服务端维护者所有连接的客户端; 异曲同工啊. 这个同样也是某些固定场景的, 不再赘述!

解释器模式, 应用范围就更窄了, 不想说了, 码字都有点累了!

总结

  1. 应用于某些场景的压根就不用管它
  2. 我们只记三大特性和六大原则就已经掌握了大部分的设计模式
  3. 要了解任何事物, 方法论很重要, 形式的东西无所谓
  • 23
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
责任链设计模式是一种行为型设计模式,用于将请求的发送者和接收者解耦,使多个对象都有机会处理该请求。该模式将这些对象串成链,并沿着这条链传递请求,直到有一个对象能够处理它为止。 责任链模式的核心是定义一个处理请求的抽象类或接口,然后让多个具体的处理者对象继承或实现这个类/接口。每个具体的处理者对象都包含一个对下一个处理者对象的引用,形成一个链式结构。 当一个请求进入责任链时,责任链中的每个处理者都有机会处理该请求。如果可以处理请求,则进行处理;如果不能处理,则将请求传递给下一个处理者,直到有一个处理者能够处理它。 责任链模式的关键点是要到合适的处理者顺序和条件。通常情况下,责任链模式适用于以下情况: 1. 有多个对象可以处理同一类型的请求,但具体由哪个对象来处理由运行时决定。 2. 不明确请求的接收者,希望请求在一个对象链中流动,直到被处理。 3. 需要动态地指定可以处理请求的对象集合。 使用责任链模式可以实现请求发送者和接收者的解耦,增加代码的灵活性和可扩展性。但同时也需要注意责任链的长度和效率问题,避免责任链过长或造成性能问题。 总结一下,责任链设计模式是一种将请求发送者和接收者解耦的设计模式,通过将多个处理者对象串成链,沿着这条链传递请求,直到有一个处理者能够处理它。这样可以增加代码的灵活性和可扩展性,适用于有多个对象可以处理同一类型请求的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值