想着用讲故事的方式对各个设计模式进行一个稍微形象一些的描述. 当然, 某些因为没有想到特别好的例子, 可能比喻的并不是那么的恰当, 望赐教. 绞尽脑汁啊, 尽力贴近设计模式其本来的意图. 主要为了加强一些自己对设计模式的理解. 进入正题:
小王是一名心怀梦想的90后青年, 他独自创办了太原现代科技公司, 并召集了一帮志同道合的小伙伴, 梦想改变世界.
单例模式
太原现代科技公司接到了一个项目, 这时就需要大家发挥各种聪明才智了. 于是, 每个人都将自己的想法记录下来, 然后等到每天开会的时候把每个人的新想法收集起来, 统一进行讨论.
没几天, 小王就发现了这种方式的低效, 如果能够将每个人的想法实时的收集起来就好了. 这样每个人都能够实时看到其他人的新想法, 在思考的同时还能够激发自己的灵感. 问题是如何实现呢? 有一个东西叫做多人在线协作文档, 就用它了. 创建一个文档, 每个人的新想法都写到这个文档中, 每个人看到和操作的都是同一个文档.
小王的团队利用这个公共文档, 很快碰撞出了新奇的想法, 项目大获成功.
单例模式: 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.
工厂方法模式
公司最近开始了新的市场尝试, 开网店. 卖什么呢? 从小孩子入手, 刚开始嘛, 先简单涉猎一下. 就卖铅笔盒. 但是自己毕竟并不会生产, 毕竟整个厂子投入有些大, 也没有必要. 联系了文具厂 A、B、C, 只卖三个品牌的铅笔盒. 每次进货的时候, 只需要分别告诉他们自己需要铅笔盒, 而不需要告诉具体的品牌, 因为他们知道自己生产的品牌. 如此一来, 对于公司来说, 三个生产厂家其实是一样的, 只需要告诉他们: "我要铅笔盒" 即可.
工厂方法模式: 定义一个用于创建对象的接口,让子类决定实例化哪一个类. 工厂方法使一个类的实例化延迟到其子类
抽象工厂模式
之前的铅笔盒买的很好, 小王决定扩大规模. 不光卖铅笔盒, 还要卖碳素笔, 橡皮等. 厂家还是原来的三家, 毕竟已经合作这么久了. 同样的, 进货的时候也不需要指定品牌, 只要告诉他们: "我要铅笔盒", "我要碳素笔", 即可. 操作起来一样很方便.
(对了, 抽象工厂还有个更形象的例子, 那就是跨平台. 比如一个软件要在 Windows, Linux, MaxOS 下运行, 可以通过抽象工厂来消除操作系统之间的差异, 对使用者来说, 调用接口完全一致)
抽象工厂模式: 为创建一组相关或互相依赖的对象提供一个接口,而且无须制定它们的具体类
建造者模式
这天, 小王下班回到家, 看到媳妇在做饭. 因为之前每次都是一回家就吃到热腾腾的饭菜, 所以她自然也就没有关心过饭菜是如何做成的. 今天闲来无事, 进厨房帮帮忙, 就拿简简单单的煮米饭为例, 要经过淘米、加水、开火等步骤, 而一些菜的制作步骤则更是繁琐. 自己之前只知道吃米饭, 米饭做好了, 吃菜, 菜做好了. 想到这, 小王更觉得自己应该多关心关心媳妇了, 不过没多大一会, 他就因为笨手笨脚被赶出了厨房.
建造者模式: 将一个复杂对象的构建与它的表示分离, 使得同样的构建过程可以创建不同的表示
模板方法模式
公司因为扩张, 现在需要再招进一些人才来, 既然招人, 那少不了各种流程, 不然整个都乱了嘛. 一个新员工的入职流程如下: 收简历 -> 简历筛选 -> 部门面试 -> 人事面试 -> 小王面试 -> 办理入职. 即使流程明确了, 在 简历筛选, 部门面试这两个步骤, 各个部门之间是有差异的, 要由各个部门来进行具体操刀, 当然, 大的流程是不变的. 所以现在的流程很明确了, 整体流程各个部门完全一致, 各部门只需要处理其中的 简历筛选 和 部门面试两个环节就可以了.
模板方法模式: 定义一个操作中的算法的框架,而将一些步骤延迟到子类中. 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
原型模式
在公司内部, 难免要进行资源之间的共享. 当然现在智能化办公, 更多的是电脑之间的资源共享. 如何实现资源的共享呢? 还好现代操作系统都提供的复制粘贴的功能. 文件 A 可以通过复制粘贴的操作, 产生很多个完全相同的文件, 这些文件可能下发到不同人的手中来进行不同的业务处理. (对于原型模式来说, 这个复制的操作是由文件自己来完成的)
原型模式: 用原型实例指定创建对象的种类, 并且通过拷贝这些原型创建新的对象.
代理模式
最近公司发现有些某媒体滥用本公司的知识产权而没有得到授权, 所以决定通过法律的手段进行维权. 既然要走法律的流程, 那专业的事情自然要交给专业的人来办, 律师. 请律师有什么好处呢? 想象一下如果没有律师, 你需要事前准备、事后追进、出庭上诉等等一系列的事情, 而请了专业人士就不一样了, 你只需要在开庭的时候出庭, 而其他的一些事前及善后都有人来处理了, 你完全不用关心.
代理模式: 为其他对象提供一种代理以控制对这个对象的访问
中介者模式
小丽是公司的一名员工, 最近老板交给她一个任务, 公司所在的办公地址快要到期了, 要小丽找一个新的办公楼. 于是小丽就出去挨家挨户打听哪里有房出租, 然后再依次找房主进行谈判. 就这么过了两天, 可把小丽给折腾够呛, 房子也还没有着落.
小丽心想, 这也不是个办法啊. 她走在回家的路上, 看到道路旁边有一家 XX 房屋中介, 进去一问, 嘿, 合适. 将需要的信息记录在案, 第二天, 接到了中介打来的电话, 房子找到了. 经过这次, 小丽明白了一个道理, 专业的事情还是要交给专业的人来吧. 自己只要告诉中介需要什么房子, 连房主都不需要见到, 房子就租下来了, 比起自己出去找, 效率不知道高了多少倍.
中介者模式: 将多个对象间的交互委托给中介者进行, 从而降低类之间的耦合
责任链模式
当公司要下达命令时, 小王并不会依次的去通知公司的每一个人. 而是只将命令传达给秘书, 秘书再传达给各经理, 这样一层一层的将命令下发出去, 若员工小张接到命令, 发现是交给自己的任务, 那他就可以进行处理了. 而小王通过这样处理, 只需要将命令交给秘书, 就可以确保最终一定可以到达需要处理的人手中. 每个人在自己无法处理的时候, 都会将命令传递给下一个人, 最终传到处理的人手中. 对于小王来说, 那操作简单了, 不管什么命令, 统一交给秘书就好了. 而对于每一个人来说, 亦是如此, 只要交给下一个人就行了.
责任链模式: 使多个对象都有机会处理请求, 从而避免了请求的发送者和接受者之间的耦合关系. 将这些对象连成一条链, 并沿着这条链传递该请求,直到有对象处理它为止
命令模式
在公司中, 下达一个任务并不会将任务的每个执行步骤都一一说明. 比如, 如果需要打印一份文件, 只需要说: "帮我把这份文件打印一下", 而不会说: "先把这份文件打开, 连接打印机, 点开菜单, 选择打印, 选择格式, 选择打印机….". 如果是这样, 分配任务的人也太累了吧. 所以往往只要把一个对方明白的命令布置下去, 对方自然会自行完成各个步骤来最终完成这个命令.
命令模式: 将一个请求封装成一个对象, 从而让你使用不同的请求将客户端参数化, 对请求排队或者记录请求日志, 可以提供命令的撤销和恢复功能
装饰模式
公司要举办年会, 其中有个舞蹈表演, 自然要购置上配套的服装来, 相比穿休闲装跳舞, 配上对应的服装, 舞美立刻就提升了不止一个档次, 效果也要好得多. 演员还是那个演员, 舞蹈动作也没有发生变化, 而因为换上了一套服装, 立刻增强了演出的观感体验.
装饰模式: 动态的给一个对象添加一些额外的职责
策略模式
公司最近打算投资一些刚刚起步的小公司, 于是成立了北京投资分公司. 既然要投资, 那定然不能随随便便, 所以针对不同的场景拟定了一系列的投资策略. 当需要针对教育类的公司进行投资时, 就将拟订好的教育类投资策略执行, 以此来最大可能的增加盈利的概率, 进入21世纪了嘛, 让数据来说话.
策略模式: 定义一组算法, 将每个算法都封装起来, 并且使它们之间可以互换
门面模式
公司在处理用户需求的时候, 如果产品的问题找产品、技术的问题找技术. 估计客户都要抓狂了, 人家又不知道这个需求应该找谁. 所以指定了小孙和客户进行对接, 不管用户有什么类型的需求变更, 统一都告诉小孙, 然后小孙来再来将需求分配到各个具体的部门手上. 如此一来, 客户的满意度大大提高.
门面模式: 要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行. 门面模式提供一个高层次的接口, 使得子系统更易于使用.
迭代器模式
公司最近来面试的人越来越多, 而面试官又只有那么几位, 难免会让部分面试人员稍微等待一下. 如何规范的管理这个过程呢? 要让早到的人更早的面试. 排队, 没错简单粗暴的排队. 每次面试完一位之后, 只要说: "下一位", 就可以按照顺序进行下一场面试了. 当然, 你也可以问问还有没有面试人员, 如果没有就不用叫下一位进来咯.
迭代器模式: 它提供一种方法访问一个容器对象中各个元素, 而又不需暴露该对象的内部细节
适配器模式
公司的软件有用户使用了, 难免会收到用户各种问题的反馈, 但是用户每个人填写反馈信息的格式都比较随意, 比如问题描述、问题类型、发生频率等等, 用户整体都放到描述中了, 如此一来, 查看反馈信息自然就成为了一个十分困难的事情. 作为一个互联网公司, 自然想到了通过软件来解决问题. 于是开发了这样一款程序, 可以将反馈的各个数据从用户的描述中提取出来, 然后分门别类的展现在面前. 嗯, 这样一来处理反馈的问题就比之前舒服多了, 而且效率也快得多了.
适配器模式: 将一个类的接口变换成客户端所期待的另一种接口, 从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作
组合模式
随着公司的规模变大, 有必要进行公司的层次化, 也方便管理些. 例如董事会管理下边的各个子公司、各子公司下边又开设多个不同部门、各个部门下又有多个小组… 如此一来, 整个公司架构就成了一个树形的结构, 就像一个家族的族谱一样. 架构清晰了, 管理起来也就较之前方便的多了.
组合模式: 将对象组合成树形结构以表示 "部分-整体" 的层次结构,使得用户对单个对象和组合对象的使用具有一致性.
观察者模式
小王的公司接到一个项目, 在一个大商场里, 难免会有些偷偷摸摸的人拿了东西不付款, 所以该商场在每个出入口各安排了一名警务人员, 负责对所有出商场的人进行例行检查. 但这无疑会极大的耗费成本. 所以想请小王来帮着通过科技的手段解决一下面临的问题.
小王在公司召开会议, 研讨此事的解决方案, 大家都各抒己见. 最终敲定了一个方案, 在每个出口, 不设专门的人员检查, 只安装一部机器, 该机器会自动对每个出入的人员进行检查, 当检查到没有付款的客人时, 会通知警务人员过来处理. 自从安装了这个设备, 商场多个出口, 只需要配置一个警务人员就可以处理了, 而这个警务人员也不用到每个出口盯梢, 只要坐着等报警装置发出通知, 当接收到通知后, 自己再过去处理就行了.
观察者模式: 当满足某个条件时, 会顺序调用预先定义好的方法
访问者模式
公司每月要给每个员工发工资, 而对于不同的员工, 工资的计算标准是不一样的. 有的人每天工资100, 有的人每天这是500, 而有的人是计算时薪, 有的人计算日薪, 有的人计算年薪. 针对这种情况, 就要进行差异处理, 针对不同的薪资制度, 指定不同的计算规则, 在计算薪资时, 虽然各个员工的计算基数是一样的(时间), 但是因为规则不同, 计算出的薪资也自然不同.
访问者模式: 封装一些作用于某种数据结构中的各元素的操作, 它可以在不改变数据结构的前提下定义作用于这些元素的新的操作
备忘录模式
小胡是公司的后端技术开发人员, 有时难免会在工作 A 中临时被叫走解决一些其他的问题, 当问题解决完回来后, 经常无法快速进入之前的工作状态, 忘记了之前的工作进度, 甚至忘记了之前在做什么工作, 这让他很是苦恼. 不过最近经过高人指点, 发现了备忘录这个神奇的东西, 每次在工作中断的时候, 通过备忘录将当前的工作进度等记录下来, 当回来是翻看备忘录可以快速恢复到之前的工作状态.
备忘录模式: 在不破坏封装性的前提下, 捕获一个对象的内部状态, 并在该对象之外保存这个状态. 这样以后就可将该对象回复到原先保存的状态
解释器模式
小王还没有到家, 就收到了妻子发来的消息: "快到家了么?". 这句话想必是个中国人就能看懂. 但是小王毕竟不是一般人, 他由此想到了: "快" 是一个时间上的量词, "到家了" 是一个空间上的状态, "么" 是一个疑问预期词, "?"标识句子结束. 而这一连串的处理, 都是大脑在无意识之中帮我们做了.
解释器模式: 给定一门语言,定义它的文法的一种表示, 并定义一个解释器, 该解释器使用该表示来解释语言中的句子
状态模式
小李是现代科技公司北京投资分公司的董事长, 总公司每月会定期的对分公司的投资报表, 账上流水进行核实查验. 而投资公司的投资方向也是由总公司调查后定下的. 即, 总公司将投资方向告知后, 其他一概不管, 即可每月正常查验. 而内部的资产切换等等, 都是由子公司来实现的, 总公司一概不去关心.
状态模式: 由调用者将状态设置好, 对象可根据不同的状态有不同的表现
桥梁模式
公司最近因为人员增加, 需要购置一批新的计算机用于办公, 购买了几种不同品牌的计算机, 包括惠普、联想、戴尔、华硕等等, 对于员工来说, 其实并不关心使用的是什么品牌的计算机, 对于各种品牌的计算机, 即使其内部构件不同, 但是使用上来说没有什么区别.
桥梁模式 :将抽象和实现解耦, 使得两者可以独立的变化
享元模式
在公司中为了减少不必要的浪费, 有一些资源是大家共享的, 比如饮水机、打印机等等, 这些资源是谁用到的时候就去用, 没人用的时候就放在那里等待被使用. 以此达到资源的利用最大化.
享元模式: 使用共享对象可有效的支持大量的细粒度的对象
终于写完了, 这文章写到中间一度差点放弃了. 这两天决定逼一定要自己写完. 主要这玩意网上找半天也没有人将设计模式比做故事, 纯靠想象, 有了当初小学被老师逼着一天一篇想象文的感觉. 写完了舒服多了, 这文章有个草稿, 被拖了一个多月了, 估计不逼自己一把, 这文章就搁置了.
最后, 祝愿小王的公司越来越好…