设计模式是什么
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了可重用代码、让代码更容易被他人理解、提高代码的可靠性。
设计模式的分类
设计模式分为三大类:创建型模式、结构型模式和行为型模式。
创建型模式:共五种,包括单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。这些模式涉及对象的创建方式。
结构型模式:共七种,包括适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。这些模式涉及类或对象之间的连接关系。
行为型模式:共十一种,包括策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。这些模式涉及类或对象之间的职责分配。
此外,还有并发型模式和线程池模式。
部分设计模式介绍
创建型设计模式
工厂方法模式
工厂方法模式(Factory Method Pattern)是一种常用的设计模式,它是一种创建型模式。它的核心精神是封装类中变化的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。
工厂方法模式包含四个角色:抽象工厂(Abstract Factory)、具体工厂(Concrete Factory)、抽象产品(Abstract Product)和具体产品(Concrete Product)。
抽象工厂定义了一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。具体工厂是抽象工厂的子类,它负责实现抽象工厂接口中定义的所有方法,并返回对应的具体产品对象。
抽象产品是工厂方法模式中的抽象类或者是接口,它定义了一系列的规范,而具体产品则是抽象产品的子类,它实现了抽象产品所定义的所有规范。
使用工厂方法模式的优点在于,将对象的创建与使用分离,使得代码更加灵活方便。当需要添加新的产品时,只需要创建一个新的具体工厂和具体产品类即可,而不需要修改已有的代码,从而实现代码的扩展。同时,工厂方法模式也可以使得代码更加易于维护。
类图为:
结构型设计模式
适配器模式
适配器模式(Adapter Pattern)是一种设计模式,它允许将一个接口转换成另一个接口,以便不兼容的类可以一起工作。这种模式主要用于解决接口不兼容的问题,或者将已有的类引入新接口,以提供更大的灵活性。
适配器模式包含两个角色:目标接口(Target)和适配器(Adapter)。目标接口是客户端需要调用的接口,而适配器则是将目标接口转换成另一个接口的实现类。适配器将目标接口转换成客户端所需的接口,以便客户端可以直接调用它。
适配器模式有两种类型:对象适配器模式(Object Adapter Pattern)和类适配器模式(Class Adapter Pattern)。
对象适配器模式中,适配器容纳一个它包裹的类的实例。在这种情况下,适配器调用被包裹对象的物理实体。
类适配器模式中,适配器继承自已实现的类(一般多重继承)。在这种模式下,适配器被认为是一个替代者,它替代了目标对象,并提供了相同的接口。
适配器模式的主要优点在于它能够将不兼容的接口转换成兼容的接口,使得它们可以一起工作。此外,适配器模式还可以使得代码更加灵活,以便在需要时可以轻松地添加新的适配器。
类图为:
装饰器模式
装饰器模式是一种结构型设计模式,它允许您向现有的对象添加新的功能,而不会改变其现有结构。这种模式提供了一个装饰类,用于包装原有的类,并在保持类方法签名完整性的前提下,添加额外的功能。装饰器模式可以用于动态地给一个对象添加一些额外的职责,而不是通过生成子类或者扩展类的做法。这种模式通常在想要扩展类的功能时使用,而不希望修改原有类或增加大量子类的数目时。
在装饰器模式中,共有三个角色:抽象构建角色(Component)、抽象装饰角色(Decorator)以及具体装饰角色(Concrete Decorator)。抽象构建角色定义了一个抽象接口,用于接受对象并返回装饰后的对象。抽象装饰角色实现了抽象构建角色的接口,并持有一个抽象构建角色的实例,用于向其添加新的功能。具体装饰角色负责实现抽象装饰角色的接口,并向其添加新的功能。这个角色可以链式调用装饰器,从而将多个装饰器应用到同一个对象上。
使用装饰器模式的优点在于它提供了一种动态地给对象添加功能的机制,而不需要生成大量的子类或者修改原有类的代码。此外,装饰器模式还可以将具体的功能职责划分得更加清晰,从而使得代码更加易于维护和扩展。缺点是添加装饰器会导致类的结构变得更加复杂,同时也会增加对象的数量和内存消耗。
类图为:
行为型模式
策略模式
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法族,将每个算法封装起来,并且可以相互替换使用。策略模式让算法独立于使用它的客户而变化,使得我们可以更容易地改变算法的实现,而不会影响整个系统的结构。
在策略模式中,有两个主要的角色:环境类(Context)和策略类(Strategy)。环境类是一个抽象类,用于定义客户端使用的策略接口,并在使用策略时调用相应的策略方法。策略类是一个抽象类或者具体类,它实现了环境类所定义的接口,并且提供具体的策略实现。
策略模式的优点是可以使得算法的变化独立于客户端,便于替换和扩展新的算法;缺点是需要维护额外的代码和数据结构,增加了系统的复杂性和内存消耗。
策略模式适用于以下场景:
- 有多种算法需要实现的情况下,可以使用策略模式来封装每种算法的实现,并且可以相互替换使用。
- 需要动态地改变算法的情况下,可以使用策略模式来封装算法实现,并且可以通过改变实例化策略对象来实现算法的动态改变。
- 需要屏蔽算法细节的情况下,可以使用策略模式来封装算法实现,并且只暴露公共的接口给客户端使用,从而隐藏内部实现细节。
- 需要扩展算法功能的情况下,可以使用策略模式来扩展现有算法的功能,而不必修改原有代码。
类图为:
模板模式
模板模式(Template Pattern)是一种行为型设计模式,它定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板模式使得子类可以在不改变算法结构的情况下,重新定义算法的某些特定步骤。
在模板模式中,通常包含一个抽象类和一个具体类。抽象类定义了一个算法的骨架,而具体类实现了这个算法的一些具体步骤。子类可以继承抽象类,并实现其中所定义的方法来改变算法的行为。
模板模式的优点是可以将算法的骨架和具体实现分离,使得子类可以在不改变算法结构的情况下,重新定义算法的某些特定步骤。这可以提高代码的可重用性和灵活性。缺点是会增加类的数量和系统的复杂性。
模板模式适用于以下场景:
-
有一些通用的方法,需要在每个子类中都实现,可以使用模板模式将这些通用方法抽象出来,并在抽象类中定义,而具体的实现由子类来完成。
-
需要在算法结构不变的情况下,改变算法的某些特定步骤,可以使用模板模式来定义一个算法的骨架,并将可变的步骤延迟到子类中实现。
-
需要隐藏实现细节的情况下,可以使用模板模式来定义一个算法的骨架和具体实现,并且只暴露公共接口给客户端使用,从而隐藏内部实现细节。
类图为:
迭代器模式
迭代器模式(Iterator Pattern)是一种行为型设计模式,它提供了一种遍历聚合对象中各个元素的方法,而无需暴露聚合对象的内部表示。迭代器模式包含一个迭代器类,它具有提供访问容器中的元素、向前或向后遍历元素以及测试容器是否还有更多元素的功能。
在迭代器模式中,主要有以下角色:
- 迭代器接口(Iterator Interface):定义了访问和遍历元素的接口。
- 具体迭代器类(Concrete Iterator Class):实现了迭代器接口,为聚合类提供了具体的遍历方法。
- 抽象聚合类(AggregateInterface):定义了提供具体迭代器的接口,以及与迭代器相关的操作。
- 具体聚合类(Concrete Aggregate Class):创建具体迭代器,并实现与迭代器相关的方法。
使用迭代器模式的优点是可以隐藏聚合对象的底层表示,使得客户端无需关心聚合对象的内部结构。同时,还可以通过统一的遍历接口访问不同类型的聚合对象,实现不同聚合对象的共享。缺点是需要为每个聚合类单独实现迭代器类,可能会增加代码的复杂度和维护成本。
迭代器模式适用于以下场景:
- 需要隐藏聚合对象的底层表示时,可以使用迭代器模式来隐藏聚合对象的内部表示,同时提供统一的遍历接口。
- 需要支持多种遍历方式时,可以使用迭代器模式来实现不同的遍历方式,同时保持接口的一致性。
- 需要支持动态变化时,可以使用迭代器模式来支持动态添加、删除元素等操作,而不会影响聚合类的接口和客户端的使用。
类图为:
访问者模式
Visitor模式,也称为访问者模式,是一种行为型设计模式。它主要用于处理对象结构中的元素,并允许在不影响原始对象结构的情况下,向其添加新的操作。
Visitor模式包含两种角色:
- 访问者(Visitor):定义了一个操作通用元素的接口,可以访问并操作元素对象。访问者本身可以包含一些状态和行为,但并不改变对象结构。
- 元素(Element): 定义了一个接受访问者访问的接口,元素对象可以接受访问者的访问,并按照访问者的要求执行相应的操作。
Visitor模式的优点是可以动态地添加新的操作,而不需要修改原有类。它可以将相关的操作集中到一个访问者类中,同时保持元素对象结构的稳定性。缺点是需要定义一个额外的访问者类来执行新操作,可能会增加代码量和复杂性。
Visitor模式适用于以下场景:
- 一个对象结构包含很多类对象,它们有不同的接口,需要对其添加新的操作。
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。
- 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。
总之,Visitor模式是一种灵活而稳定的设计模式,可以帮助我们更好地处理对象结构中的元素,并动态地添加新的操作。
类图为: