设计模式
文章目录
- 设计模式
-
- 简要说明
- 面向对象设计原则
- GoF23设计模式简要说明
- 创建型
-
- 工厂方法模式
- 抽象工厂模式
- 建造者模式
- 原形模式
- 单例模式
- 结构型模式
-
- 适配器模式
- 桥接模式
- 组合模式
- 装饰模式
- 外观模式
- 享元模式
- 代理模式
- 行为型模式
-
- 职责链模式
- 命令模式
- 解释器模式
- 迭代器模式
- 中介者模式
- 备忘录模式
- 观察者模式
- 状态模式
- 策略模式
- 模板方法模式
- 访问者模式
简要说明
由于图片上传至,大家看不见图的需要挂下代理,或者使用手机热点尝试解决。这方面问题大家请自行解决。
内容可能有一些不对的地方请见谅。
面向对象设计原则
-
单一职责原则
- 定义:一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中
- 命令模式体现了单一职责原则,大多数类都是一组方法和相应的一组变量的结合,而该模式只是封装了一个没有任何变量的函数,它对函数的关注超过了类,将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化。
- 职责链模式、备忘录模式、状态模式、访问者模式体现该原则
-
开闭原则
- 定义:一个软件实体应当对扩展开放,对修改关闭。在设计一个模块时候,应当使这个模块可以在不被修改地前提下被扩展。
- 抽象工厂体现了这个原则,如果想增加一个新的products,只需在product体系中增加一个products,然后在factory类体系结构中增加一个concrete factory就可以了,而不需要对现有类做任何修改。
-
里氏代换原则
- 定义:在软件中如果能过够使用基类(父类)对象,那么一定能够使用其子类对象。把基类都替换成子类,程序不会产生任何错误和异常,反过来则不成立。
- 里氏代换原则使实现开闭原则地重要方式之一。抽象工厂。
-
依赖倒转原则
- 定义:代码要依赖于抽象的类,而不要依赖于具体的类;要针对接口或抽象类编程,而不是针对具体类编程。
- Template method就体现了这个原则,它定义了一个操作中的算法骨架,而将一些步骤延迟到子类中,template method使得子类不改变一个算法的结构,即可重定义该算法的某些特定步骤。
- 观察者模式体现该原则
-
接口隔离原则
- 定义:一旦一个接口太大,则需要将塌分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可。
-
合成复用原则
- 定义:在一个新的对象里通过关联关系来使用一些已有的对象,使之成为新对象的一部分;新对象通过委派调用已有对象的方法达到复用其已有功能的目的。简言之,要尽量使用组合/聚合关系,少用继承
- 桥接模式体现了合成复用原则
-
迪米特法则
- 定义:一个软件实体应当尽可能少地于其他实体类发生相互作用,这样当一个模块修改时,就会尽量少地影响其他地模块,扩展会相对容易。
- 外观模式、中介者模式体现该原则
GoF23设计模式简要说明
看书P55
创建型
工厂方法模式
-
优点:
-
用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
-
灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。
-
典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,。
-
-
缺点:
-
类的个数容易过多,增加复杂度
-
增加了系统的抽象性和理解难度
-
抽象产品只能生产一种产品,此弊端可使用解决。
-
-
应用场景
-
客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
-
创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
-
客户不关心创建产品的细节,只关心产品的品牌
-
-
如要在系统中增加一个BMP格式读取器:绘制类图并修改代码。
- 某单据管理系统中要求实现对采购、销售、库存的单据管理,系统的采购类的单据中有如采购单、收货单、应付帐单、付款单和退货单等,现使用抽象工厂方法设计模式设计该系统。
- 某软件公司欲开发一个音频与视频播放软件,为了给用户使用提供方便,该播放软件提供了多种界面显示模式,如完整模式、精简模式、记忆模式、 络模式等。在不同的显示模式下主界面的组成元素有所差异,如在完整模式下将显示菜单、播放列表、主窗口、控制条等;在精简模式下只显示主窗口和控制条,而在记忆模式下将显示主窗口、控制条、收藏列表等。现要求使用建造者设计模式设计该软件。
单例模式
单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。
单例模式有 3 个特点:
- 单例类只有;
- 该单例对象;
- 单例类对外提供。
-
优点:
- 单例模式可以保证内存里只有一个实例,减少了内存的开销。
- 可以避免对资源的多重占用。
- 单例模式设置全局访问点,可以优化和共享资源的访问。
-
缺点:
- 单例模式一般没有接口,扩展困难。如果要扩展,则除了修改原来的代码,没有第二种途径,。
- 在并发测试中,单例模式不利于代码调试。在调试过程中,如果单例中的代码没有执行完,也不能模拟生成一个新的对象。
- 单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则。
-
扩展
- 饿汉式单例:在定义静态变量的时候实例化单例类
- 懒汉式单例:在第一次被引用时将自己实例化
-
应用场景
-
世界上只有一个月亮,月亮的直径是3476.28km,无论在中国还是在美国,我们所看到的都是同一个月亮。使用单例模式实现无论我们在哪所看到的月亮是同一个月亮(饿汉单例模式、懒汉单例模式),绘制类图并用Java语言编程实现。
-
结构型模式
适配器模式
适配器模式(Adapter)的定义如下:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式分为和两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。
-
优点:
-
客户端通过适配器可以透明地调用目标接口。
-
复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
-
将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
-
在很多业务场景中。
-
-
缺点:
- 适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂性。
- 增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。
-
应用场景
- 现有一个接口DataOperation定义了排序方法Sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序,类BinarySearch的binarySearch(int[],int)方法实现了二分查找算法,现使用适配器模式设计一个系统,在不修改源码的情况下将类QuickSort和类BinarySearch的方法适配到DataOperation接口中。绘制类图并编程实现。
桥接模式
桥接(Bridge)模式的定义如下:。它是用来实现,从而降低了抽象和实现这两个可变维度的耦合度。
-
优点:
-
抽象与实现分离,扩展能力强
-
其实现细节对客户透明
-
-
缺点:
- 由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,能正确地识别出系统中两个独立变化的维度,这增加了系统的理解与设计难度。
-
应用场景
- 如果系统中某对象有三个维度,如某日志记录器既可以支持不同的操作系统,还可以支持多种编程语言,并且可以使用不同的输出方式。请使用桥接模式设计该系统。
- 优点:
- 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
- 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足;
- 缺点:
- 设计较复杂,客户端需要花更多时间理清类之间的层次关系;
- 不容易限制容器中的构件;
- 不容易用继承的方法来增加构件的新功能;
- 应用场景
- 某系统提供了一个数据加密功能,可以对字符串进行加密。最简单的加密算法通过对字母进行移位来实现,同时还提供了稍复杂的逆向输出加密,还提供了更为高级的求模加密。用户先使用最简单的加密算法对字符串进行加密,如果觉得还不够可以对加密之后的结果使用其他加密算法进行二次加密,当然也可以进行第三次加密。现使用装饰模式设计该多重加密系统。
-
享元模式的主要优点是:
- 相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。
-
其主要缺点是:
-
为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。
-
读取享元模式的外部状态会使得运行时间稍微变长。
-
-
应用场景
-
某信息咨询公司推出收费的在线商业信息查询模块,需要对查询用户进行身份验证,并记录查询日志,以便根据查询次数收取查询费用,现使用代理模式设计该系统。
- 某物质管理系统中物质采购需要分批审批,主任可以审批一万元及以下的采购单,部门经理可以审批5万及以下的采购单,副总经理可以审批10万及以下的采购单,总经理可以审批20万元及以下的采购单,20万以上的需要会议审批,现采用职责链模式来设计该模拟系统。
-
实现一个通讯录程序,命令模式下的JAVA程序,该程序具备添加,删除,和查看通讯录信息的功能
界面:
1.添加联系人信息
2.删除联系人信息
3.查看联系人信息
当点击按钮添加时,以进入添加联系人信息,添加的信息包括姓名和电话 码
当点击按钮删除时,可进入删除联系人信息,通过输入联系人姓名完成删除。
当点击按钮查看时,可进行查看,通过输入联系人姓名,查看其他电话 码。
现使用命令模式来设计该系统,绘制类图并编程实现。
-
优点:
-
访问一个聚合对象的内容而无须暴露它的内部表示。
-
遍历任务交由迭代器完成,这简化了聚合类。
-
它支持以不同方式遍历一个聚合,甚至可以自定义迭代器的子类以支持新的遍历。
-
增加新的聚合类和迭代器类都很方便,无须修改原有代码。
-
封装性良好,为遍历不同的聚合结构提供一个统一的接口。
-
-
缺点:
- 增加了类的个数,这在一定程度上增加了系统的复杂性。
- 应用场景
享元模式
享元(Flyweight)模式的定义:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
迭代器模式
迭代器(Iterator)模式的定义:提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。迭代器模式是一种模式。
在日常开发中,我们几乎不会自己写迭代器。除非需要定制一个自己实现的数据结构对应的迭代器,否则,开源框架提供的 API 完全够用。
中介者模式
中介者(Mediator)模式的定义:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是的典型应用。
中介者模式是一种对象行为型模式。
-
优点:
-
类之间各司其职,符合。
-
降低了对象之间的耦合性,使得对象易于独立地被复用。
-
将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展。
-
-
缺点:
- 中介者模式将原本多个对象直接的相互依赖变成了中介者和多个同事类的依赖关系。当同事类越多时,中介者就会越臃肿,变得复杂且难以维护。
-
应用场景
备忘录模式
备忘录(Memento)模式的定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。
-
优点:
-
提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
-
实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
-
简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合。
-
-
缺点:
- 资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。
-
应用场景
观察者模式
观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
- 优点:
- 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。。
- 目标与观察者之间建立了一套触发机制。
- 缺点:
- 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
- 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
- 应用场景
状态模式
状态(State)模式的定义:对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
-
优点:
-
结构清晰,状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足。
-
将状态转换显示化,减少对象间的相互依赖。将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。
-
状态类职责明确,有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。
-
-
缺点:
-
状态模式的使用必然会增加系统的类与对象的个数。
-
状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。
-
,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源码,否则无法切换到新增状态,而且修改某个状态类的行为也需要修改对应类的源码。
-
-
应用场景
策略模式
策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
-
优点
- 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句,如 if…else 语句、switch…case 语句。
- 策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
- 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
- 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
- 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。
-
缺点
- 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
- 策略模式造成很多的策略类,增加维护难度
-
应用场景
模板方法模式
模板方法(Template Method)模式的定义如下:定义一个操作中的算法骨架,而,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。
- 该模式的主要优点如下。
- 它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
- 它在父类中提取了公共的部分代码,便于代码复用。
- 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,。
- 该模式的主要缺点如下。
- 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象,间接地增加了系统实现的复杂度。
- 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。
- 由于继承关系自身的缺点,如果父类添加新的抽象方法,则所有子类都要改一遍。
- 应用场景
访问者模式
访问者(Visitor)模式的定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。
-
优点
- 扩展性好。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
- 复用性好。可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。
- 灵活性好。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由地演化而不影响系统的数据结构。
- 。访问者模式把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一。
-
缺点
- 增加新的元素类很困难。在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这。
- 破坏封装。访问者模式中具体元素对访问者公布细节,这破坏了对象的封装性。
- 。访问者模式依赖了具体类,而没有依赖抽象类。
-
应用场景
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!