软件设计模式产生的背景

 软件设计模式最初并不是出现在软件设计中,而是源自建筑领域。1977年,美国著名建筑大师克里斯托夫·亚历山大在他的著作《建筑模式语言:城镇、建筑、构造》中描述了一些常见的建筑设计问题,并提出了253种关于城镇、邻里、住宅、花园和房间等进行设计的基本模式。这些模式的概念后来被引入到软件设计领域,并在1990年代得到了广泛的研究和应用。

1990年,软件工程界开始研讨设计模式的话题,并召开了多次关于设计模式的研讨会。直到1995年,艾瑞克·伽马、理查德·海尔姆、拉尔夫·约翰森、约翰·威利斯迪斯等四位作者合作出版了《设计模式:可复用面向对象软件的基础》一书,在此书中收录了23个设计模式,这标志着软件设计模式的突破。这四位作者在软件开发领域里也以他们的“四人组”(Gang of Four,GoF)著称。

软件设计模式的概念

 软件设计模式的概念是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方案。设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。

正确使用设计模式的优点

正确使用设计模式可以提高程序员的思维能力、编程能力和设计能力,使程序设计更加标准化、代码编制更加工程化,提高软件开发效率,缩短软件的开发周期,并使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。

设计模式的分类及简介

创建者模式

 创建型模式关注对象的创建过程,提供了一种在创建对象时解耦对象的创建和使用的方式。这些模式有助于降低系统的耦合度,使得对象的创建过程更加灵活和可控。

创建者模式的分类

 创建者模式主要包括一下几种:

  1. 单例模式:确保一个类只有一个实例,并提供一个全局访问点。
  2. 简单工厂模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。
  3. 抽象工厂模式:提供一个接口,用于创建一系列相关或依赖对象,而无需指定它们具体的类。
  4. 建造者模式:通过复制现有的实例来创建新实例,而不是通过新建实例的方式。
  5. 原型模式:封装一个对象的构建过程,并允许该过程逐步构建。

创建者模式的应用

 每种创建型模式都有其特定的应用场景,例如以下场景:

  • 单例模式常用于需要全局唯一实例的场景,如数据库连接池、配置管理器等。
  • 工厂方法模式适合于当产品族中的产品数量较少,且产品之间的差异不大时使用。
  • 抽象工厂模式适用于当系统需要创建一系列相关或相互依赖对象的时候。
  • 建造者模式适合于创建复杂对象,尤其是当对象的内部结构复杂,需要分步骤构建时。
  • 原型模式则适用于当创建新对象的成本较高,或者需要快速生成大量相似对象时。

创建者模式的优缺点

 每种创建型模式都有其优点和缺点,选择合适的创建型模式取决于具体的应用场景和设计需求。在设计系统时,应当根据实际情况权衡各种模式的利弊,以达到最优的设计效果。

  • 单例模式可以确保全局只有一个实例,便于管理和控制,但如果滥用可能会导致代码难以测试和维护。
  • 工厂方法模式可以提高代码的灵活性,但可能会增加系统的复杂性。
  • 抽象工厂模式可以促进系统的扩展,但如果产品族过多,可能会导致系统过于庞大和难以管理。
  • 建造者模式可以很好地控制对象的创建过程,但如果对象的构建步骤过多,可能会导致代码冗长和难以理解。
  • 原型模式可以提高对象的创建效率,但如果对象的复制过程复杂,可能会影响性能。

结构型模式

 结构型模式关注如何将类或对象按某种布局组成更大的结构。这些模式通常用于描述类或对象的组合方式,以便在保持系统灵活性的同时,实现更复杂的功能。

结构型模式的分类

 结构型模式可以分为类结构型模式对象结构型模式两大类。

类结构模式

 类结构型模式关心类的组合,由多个类可以组合成一个更大的系统。在类结构型模式中,通常只存在继承和实现关系。常见的类结构模式有:

  1. 适配器模式 (Adapter):将一个类的接口转换成客户期望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。
  2. 桥接模式 (Bridge):将抽象部分与实现部分分离,使它们可以独立变化,降低了抽象和实现之间的耦合度。
  3. 装饰模式 (Decorator):动态地给一个对象添加一些额外的职责,即增加其额外的功能,而不改变其原有的结构。
  4. 外观模式 (Facade):为子系统中的一组接口提供一个一致的高层接口,简化了客户端与子系统之间的交互。
  5. 享元模式 (Flyweight):通过共享技术有效地支持大量细粒度对象的复用,减少了内存消耗。
  6. 代理模式 (Proxy):为其他对象提供一种代理以控制对这个对象的访问,可以限制、增强或修改该对象的一些特征。
对象结构型模式

 对象结构型模式则关心类与对象的组合,通过关联关系使得在一个类中定义另一个类的实例对象,然后通过该对象调用其方法。根据“合成复用原则”,在系统中尽量使用关联关系来替代继承关系,因此大部分结构型模式都是对象结构型模式。常见的对象型模式是 组合模式 (Composite),组合模式将对象组合成树形结构以表示部分-整体的层次结构,使得客户端对单个对象和组合对象的使用具有一致性。

结构型模式的应用

结构型设计模式在软件设计中的应用非常广泛,它们不仅能够提高系统的可维护性和可扩展性,还能够帮助开发者更好地理解和管理系统的结构。在实际的软件开发过程中,结构型设计模式常与其他设计模式结合使用,以满足不同需求的软件开发。结构型设计模式在多个领域的软件设计中经常被应用,例如:

  1. 适配器模式:在需要整合不同接口的系统中,适配器模式可以将一个类的接口转换成客户端所期望的另一个接口,使得原本不兼容的类能够一起工作。

  2. 桥接模式:当系统需要对几种功能相互组合时,桥接模式可以将抽象部分与实现部分分离,使它们可以独立变化。这种模式特别适用于系统有多个维度的变化,且各维度需要进行独立的扩展时。

  3. 组合模式:组合模式将对象组合成树形结构以表示"部分-整体"的层次结构。这种模式使得用户对单个对象和组合对象的使用具有一致性,适用于处理具有部分整体关系的场景。

  4. 装饰器模式:装饰器模式允许在不修改对象的情况下,动态地增加对象的功能。这种模式提供了一种灵活的方式来扩展对象的功能,特别适用于系统需要扩展功能,但不希望使用继承方式进行扩展的情况。

  5. 外观模式:外观模式为子系统中的一组接口提供一个统一的接口,简化复杂系统的接口,使得客户端更容易使用。这种模式适用于需要对用户来说比较复杂的系统,通过提供一个简化的接口,来减少用户的操作难度。

  6. 享元模式:享元模式运用共享技术来有效地支持大量细粒度对象的复用。这种模式可以减少系统中对象的数量,从而提高系统的性能,特别适用于系统底层的开发,解决系统的性能问题。

  7. 代理模式:代理模式为其他对象提供一种代理以控制对这个对象的访问。这种模式可以在不改变原始对象的情况下,通过引入代理对象来控制对原始对象的访问,适用于需要对原始对象进行保护或延迟加载的场景。

结构型模式的优缺点

优点

 结构型模式通过组合而非继承的方式,动态地扩展一个对象的功能,在运行时选择不同的装饰器,从而实现不同的行为可以提高代码的灵活性和可拓展性;通过组合关系或聚合关系代替继承关系,降低了类之间的耦合度,使得系统的各个部分可以独立变化而不影响其他部分;通过将通用的功能抽取出来,结构型模式可以促进代码的重用,减少重复代码的编写;结构型模式可以简化设计,使得复杂的系统结构变得更加清晰易懂。

缺点

 虽然结构型模式具有很多优点,但是也存在一些缺点。过度使用结构型模式可能会增加系统的复杂性,使得代码难以理解和维护。某些结构型模式,如代理模式,可能会在客户端和目标对象之间增加一个代理对象,这可能会导致请求处理速度变慢。 但是与其优点相比博主觉得这点还是可以接受的,而且只要不是过度的使用而且使用合理的话对于处理速度的影响微乎其微。如果不恰当地使用结构型模式,可能会导致设计不当,例如滥用适配器模式可能会使系统代码变得混乱。

 虽然结构型模式旨在遵循设计原则,但如果使用不当,可能会违反这些原则,例如过度使用装饰模式可能会导致类的膨胀。

行为型模式

行为型模式的分类

行为型模式关注于对象之间的通信和职责分配,以及算法的封装。这些模式描述了对象之间的交互方式,以及如何通过这些交互来完成任务。行为型模式通常用于处理对象之间的复杂关系,包括合作、委托、状态变化等。常见的行为型模式有:

  1. 责任链模式(Chain of Responsibility)责任链模式允许多个对象处理一个请求,每个对象决定是否继续传递请求给链上的下一个对象。这种模式减少了对象之间的耦合,使得系统更加灵活。
  2. 命令模式(Command)命令模式将请求封装为对象,使得请求可以被存储和传递,也可以被参数化。这种模式通常用于实现撤销操作和宏命令。
  3. 解释器模式(Interpreter)解释器模式提供了定义语言的文法以及如何解释这些语言的方法。它通常用于编译器设计和文本解析。
  4. 迭代器模式(Iterator)迭代器模式提供了一种方法来顺序访问一个聚合对象中的元素,而无需暴露聚合对象的内部表示。这种模式常用于遍历集合数据。
  5. 中介者模式(Mediator)中介者模式定义了一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度。
  6. 观察者模式(Observer)观察者模式定义了对象间的一对多依赖关系,当一个对象状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
  7. 状态模式(State)状态模式允许一个对象在其内部状态发生改变时改变其行为。
  8. 策略模式(Strategy)策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。
  9. 模板方法模式(Template Method)模板方法模式定义了一个操作的算法骨架,将一些步骤延迟到子类中实现。
  10. 访问者模式(Visitor)访问者模式在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式。
  11. 备忘录模式(Memento)备忘录模式在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。

行为型模式的应用

 行为型模式广泛应用于软件工程中,它们有助于提高代码的可重用性、可维护性和灵活性。例如,在Web应用程序中,可以使用命令模式来处理用户输入的动作;在游戏开发中,状态模式可以用来管理游戏对象的不同状态;在系统架构设计中,中介者模式可以用来隔离不同模块之间的交互,降低系统复杂度。

行为型模式的优缺点

优点

 行为型模式主要关注对象之间的交互和协作,它们有助于清晰地划分类和对象的职责,并研究在运行时实例对象之间的交互。行为型模式通过定义对象之间的交互方式,可以使系统更加灵活和可扩展,便于后续的修改和拓展;行为型模式通过定义对象之间的交互方式,可以降低系统的耦合度,使得系统的各个部分更加独立,便于维护和升级;行为型模式鼓励使用继承和组合等技术,有助于代码的复用,减少重复代码的编写;由于行为型模式强调对象之间的交互,这有助于设计出更易于测试的系统,提高代码的可靠性和稳定性。

缺点

 虽然行为型模式带来了许多好处,但也存在一些潜在的缺点。过度使用行为型模式可能会导致系统变得复杂,难以理解和维护;为了实现特定的行为,可能需要创建大量的类和对象,这可能会导致代码膨胀,增加系统的负担;在某些情况下,行为型模式可能导致设计过于抽象,难以把握具体的业务逻辑。

总结

 通过以上的介绍我们可以发现设计模式是一把双刃剑,利用的恰当可以让我们的系统变得更加灵活、健壮、优雅。但是如果滥用设计模式会使我们的系统变得更加死板、脆弱。要想使用好设计模式设计出更加优雅的系统需要我们特别熟悉每一种设计模式的主要思想以及常见的运用场景。

 在对某种设计模式了解的不够深入之前博主认为最好不要使用,因为很容易造成滥用导致系统后期变得更加难以维护。我们在设计系统的一开始就要好好思考如何去设计,如何更好的利用设计模式,以避免在后续开发中需要反复修改代码,甚至不去修改导致代码变成了屎山代码……。

 博主认为如何设计出更加优雅的系统需要我们不断的去思考去总结,这里的优雅指的是系统应具备以上设计模式的优点,做到灵活、健壮、易于维护。设计出更加优雅的系统应该是我们每一个开发者的目标。

06-14 03:12