【设计模式】之23种设计模式的基本原理及例子

1 设计模式六大原则

1.1 单一职责原则

原理

  在软件组件设计中,如果责任划分不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任;

例子

  手机与数码相机对比,虽然手机功能多样可以打电话、拍照、打游戏等等…,而相机只有拍照的功能;但是,假设有某一时刻,天空出现了UFO,这时如果拿出手机进行拍照则需要经过解锁->打开相机软件->拍照;如果用相机则只用开机就可以拍照了;这就完全诠释了单一职责的特点,即如果一个类耦合了太多功能,则使用它将可能会带有一些不必要的操作;

1.2 开放-关闭原则

原理

  开闭原则指的是:对扩展开发,对修改关闭;

例子

  弹性制上班、下班时间:如果规定上下班的时间,有些难免碰到堵车等意外情况迟到;这种情况不可控制;如果想改善这种情况可以改成弹性上班制,其实老板要的只是员工保证每天8小时的上班时间即可;这就体现了对工作时长的修改关闭,对时间制度扩展的开放。

1.3 依赖倒转原则

原理

  抽象不应该依赖细节,细节应该依赖于抽象;简单地说就是面向接口编程,不要面向实现编程。

例子

  电脑的主板、CPU、内存或是硬盘都是在针对接口设计,如果针对实现来设计那么内存将对应都某个具体的牌子主板来设计,将来如果要讲内存换了就面临把主板也换了的尴尬情况;

1.4 里氏替换原则

原理

  子类型必须能够替换掉他们的父类型。

例子

  鸽子继承鸟类,此时鸽子就拥有了鸟类可以有飞行功能;并且此时鸽子可以代替鸟类执行飞行功能;

1.5 迪米特法则

原理

  也叫最少知道法则,针对两个类来说,如果其中一个类要调用另一个类,可以通过第三者转发这个调用;这样做可以降低两个类之间的耦合,如果其中一个类进行修改不会对有关系的类造成波及;

例子

  新人入职领取并安装电脑例子:其中新人的目的是领取到自己的电脑,并且可以正常使用;但是他并不想自己去找到具体干活的人;这时就可以通知IT部门的主管,让他给安排一个人来为自己安装电脑;如果是自己去找某个人来干活的话可能还要考虑这个人是否有空什么的,就很麻烦;

1.6 合成/聚合服用原则

原理

  尽量使用合成聚合,尽量不使用类继承。

例子

  雁群包含大雁(雁群弱引用大雁);大雁包含翅膀(大雁强引用翅膀);

2 创建型

  创建型指的是如何去实例化对象的问题

2.1 工厂模式

2.1.1简单工厂模式

原理

  通过对象的一个代号,到工厂中获取想要的一个对象;工厂内通过 switch 去调到指定分支创建对象;

例子

  计算器工厂,通过向工厂输入运算符,工厂就实例化出合适的对象;

2.1.2 工厂方法模式

原理

  定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

例子

  计算器工厂,定义加法器工厂、减法工厂、乘法工厂等等;各个工厂负责创建各自负责的对象;如果将来要扩展计算功能,只要新增工厂就可以了;

2.1.3 抽象工厂模式

原理

  提供一个创建一系列相关或互相依赖对象的接口,而无需指定他们具体的类;

例子

  组装一台台式电脑,需要创建显示器、主机、键盘、鼠标、耳机对象等等;这些对象如果用工厂方法模式需要用到多个工厂来完成;这时我们可以定义一个抽象工厂,里面定义多个抽象方法来完成对显示器等配件的对象创建;然后定义一些工厂子类,比如惠普、华硕、三星等等,里面实现创建对应牌子的显示器、主机、键盘、鼠标等等;这样就方便管理电脑对象了,并且扩展性非常好;

2.2 原型模式

原理

  用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

例子

  通过clone() 方法实现对象浅拷贝,或者通过序列化和反序列化实现对象深拷贝;

2.3 建造者模式

原理

  将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

例子

  不同的人制作同一个菜品,虽然制作流程大体相同,但做出的味道可能截然不同;其中原因可能是调料的使用量不同,做菜时的火候不同等等;但是当我们去KFC这类店里吃东西的时候会发现,无论在他们的哪一家门店,同一种菜品做出的味道都惊人的相似;这是因为他们做菜时对调料的使用量和对火候的控制都有严格的标准,所以做出的东西都让人觉得口味一样。类比程序开发,如果开发者想要在创建对象时得到的对象中一些重要属性完全相同,其他属性可以不同的对象,就可以考虑使用建造者模式来实现。

2.4 单例模式

3 结构型

  结构型模式描述如何将类或对象按某种布局组成更大的结构。

3.1 代理模式

原理

  为其他对象提供一种代理以控制对这个对象的访问。

例子

  给暗恋的人送花,自己却不敢去送。这时就可以托一个代理这去帮忙送花,这个代理这聚了真实送花的对象,对外开放送花的接口时代理者的接口,而实际上则是调用了真实对象的送花方法。

3.2 外观模式

原理

  为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用;

例子

  假设在分布式系统中有编号为1 2 3这三个不同的子系统,完成一项功能需要按照顺序1-2-3才能实现,可见流程比较复杂;如果客户端不清楚这个顺序或者这三个子系统的对接比较麻烦将导致这个功能很难实现;现在定义一个高层接口去对接这三个接口,客户端想要实现功能只需要对接这个高层接口即可,这就是外观模式;但有一个缺点,外观模式的高层接口要随着子系统的改变而改变,不符合开闭原则。

3.3 适配器模式

原理

  将一个类的接口转换成客户希望的另外一个接口;他可以将原本由于接口不兼容而不能一起工作的那些类可以一起工作。

例子

  中国人熟悉英文到外国旅游,由于语言不通造成交流障碍;这时可以配备一个翻译跟在身边,这个翻译就做适配器的角色,将中文翻译成外国人能挺懂的语言并传达给对方,这就是适配器模式。

3.4 组合模式

原理

  组合模式使得用户对单个对象和组合对象的使用具有一致性。

例子

  一家公司的OA办公系统中,有多个部门,部门内又有自己的子部门和办事处;上述种种组成一颗层级分明的树结构,树中的结点分为“叶子结点”和“普通结点”两种。

3.5 桥接模式

原理

  将抽象部分与它的实现部分分离,使它们都可以独立变化。

例子

  画图软件在绘制图形时有形状和颜色两种特性供用户选择,后端很容易设计一个图形类,包含颜色和形状两个属性;这时后台可以通过继承这个图形类来扩展程序支持的图形,比如蓝色的正方形、蓝色的长方形等等等等;这样设计固然可以,但是扩展行不好,后期的维护难度也较大;可以用桥接模式来解决,同样设计一个图形类抽象类,同时设计一个颜色抽象类;图形抽象类组合了颜色抽象类,并提供 set 方法设置颜色;图形类下面有不同形状的子类支撑;程序在准备阶段设计出需要的形状和颜色,至于用户需要哪种形状和颜色的组合可以进行配置;

3.5 享元模式

原理

  享元模式通过共享技术实现相同或相似对象的重用

例子

  字符串常量池,Integer 缓存 -128-127 数值;

4 行为型

  行为型设计模式关注对象之间的通信,为对象之间的通信提供了最佳实践的模板。

4.1 策略模式

原理

  策略指的是解决问题的方法,这个方法可以有多种;既然是这样我们就可以定义一个抽象策略,将需要操作的资源定义在这个抽象类中;将实际解决问题的方案定义在他的子类中,这也体现了解决办法的一个多态特点;结合简单工厂模式来使用会更好。

例子

  收银系统有两个输入框:一个是单价,一个是数量,然后在三种策略(正常收费、打折和满减)中选择一种种策略来计算最终结果。

4.2 装饰者模式

原理

  动态给一个对象添加一些额外的职责,就增加功能来说,装饰着模式比生成子类更加灵活;

例子

  人与各种衣物的例子。衣服、裤子和鞋子是生活中必备的几样装饰品,这些装饰品通过不同的搭配和使用顺序将会展现不同的效果,所以这些装饰品需要能灵活的组装到一个人的身上。

4.3 模板方法模式

原理

  定义操作中的算法骨架,而将一些步骤延迟到子类中。简单的来说就是把不变的行为搬移到超类中,去除子类中重复的代码来体现它的优势。

例子

  考生在试卷上答题的例子:将需要考察的题目做成模板硬刷在一张试卷上,并留有空位;不同的考生在模板上填写答案;实现了对试卷最大的复用,并实现了多态;

4.4 观察者模式

原理

  观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知多有观察者对象,使他们能够自动更新自己。

例子

  一个游戏房间,这个房间能容纳10个人玩游戏。游戏开始条件:(1)当房间被创建后满10人就开始;(2)房间被创建后未满10,但是到达最大等待时间比如30秒也开始游戏。在这个游戏里面,房间就是被观察者,玩家是观察者;玩家在加入房间时会判断是否足够10人,如果够的话就改变房间的状态,并通知玩家开始游戏;至于游戏开始的第二个条件可以做一个定时器 30 秒后触发,如果房间30秒后还未开始游戏则改变房间状态,开始游戏并通知玩家;

4.5 状态模式

原理

  当一个对象的内在状态改变时,允许改变其他行为,这个对象看起来像是改变了类;

例子

  电梯主要有四种状态:电梯门关闭、天梯门打开、电梯上下运载、电梯停止。当电梯门在打开时,电梯只能关闭电梯门,不能是其他任何操作。这份逻辑在没用状态模式之前一定是长篇大论,很多if…else,而且逻辑混乱,很难维护。可以利用一个状态抽象类和子类去描述这些电梯的状态,而电梯状态之间的转换则由具体状态类中的方法来维护,这样每个状态的工作职责明确,且不容易出错。
状态模式学习连接

4.6 备忘录模式

原理

  在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

例子

  有一种通关游戏,在攻打最终Boss前将游戏进度保存;这样如果在攻打Boss失败后,可以返回刚才那个进度来恢复原来的状态,避免从头来过;这其中的原理就是把当前的游戏状态的各种参数存储,以便恢复时读取。

4.7 迭代器模式

原理

  提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。

例子

  售票员买票的例子,在旧时期的公交车会有个售票员卖票;上车的每个人都要买票,并且乘客的行李较大,占用一个位子的位置时需要多买一张票;这个售票员就像一个迭代器,遍历每个上车的人员或者是行李都会被遍历到。

4.8 命令模式

原理

  该模式将请求发起者和请求执行者解耦;并支持对请求排队或者日志记录,以及支持撤销请求的操作;

例子

  餐厅点餐,点餐人对接服务员,将需要点的菜品跟服务员说,让服务员记录下来,然后服务员再通知厨师去做菜品。

4.9 责任链模式

原理

  为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

例子

  报销单审批,根据报销单上的金额分发给不同的人进行审批;比如0-1000元直接上级审批就可以,1000-10000要财务经理审批,10000-100000要公司老板审批;

4.10 中介者模式

原理

  用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

例子

  过年回家,悲催地被催婚了,父母带你去了婚姻中介所;在这个场景里面,婚姻中介所代表中介角色,维护了所有
男士和女士的基本信息,并提供算法查找符合要求的异性;单身的男士和女士类聚合了中介对象,并把自己的基本信息注册到婚姻中介所,有需要的话就调用中介所的匹配方法去寻找合适的异性。

4.11 解释器模式

原理

  对于一些固定文法构建一个解释句子的解释器,如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。

例子

  例如给定一个表达式 a+b,让后设置 a 为1,b 为2,计算 a + b 的值。可以定义一个值解释器,它用来解释变量 a 和变量 b 的值,定义一个加法解释器,它用来解释 a + b ,即先通过值表达式解释变量 a 和变量 b 的值,然后将它们相加。

原理

  

例子

  

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值