23种设计模式最全详解

创建型模式

工厂方法模式(Factory Method)
  • 模式角色

    • 抽象工厂(Abstract Factory):提供创建产品对象的接口,系统中具体工厂类的父类或者是共有接口。

    • 具体工厂类(Concrete Factory):实现抽象工厂接口,产生具体的产品类实例。

    • 抽象产品类(Abstract Product):定义产品的规范,描述产品的主要特性和功能。

    • 具体产品类(Concrete Product):实现抽象产品定义的所有接口,并且具体产品往往由多个不同的具体产品类实现。

  • 优点

    • 可以确保创建对象的可扩展性,当需要增加一个新的产品时,只需要增加一个具体的产品类和一个具体的工厂类即可。

    • 可以让客户端更加的关注具体产品的使用,而不需要关注产品的创建细节。

  • 缺点

    • 要求创建相应的工厂类,系统中类的个数增加。
  • 适用场景

    • 当需要创建对象的时候,并且对象的类型可能会发生变化时使用工厂方法模式进行创建。
抽象工厂模式(Abstract Factory)
  • 模式角色

    • 抽象工厂(Abstract Factory):提供创建一套产品对象的接口,系统中具体工厂类的父类或者是共有接口。

    • 具体工厂类(Concrete Factory):实现抽象工厂接口,产生一套具体的产品类实例。

    • 抽象产品类(Abstract Product):定义产品的规范,描述产品的主要特性和功能。

    • 具体产品类(Concrete Product):实现抽象产品定义的所有接口,并且具体产品往往由多个不同的具体产品类实现。

  • 优点

    • 分离接口和具体的实现,客户端可以通过抽象工厂更加方便地使用一套产品族(一组相关联的产品)而不需要关注产品的具体实现。

    • 产品族内的约束是非常强的,给设计师一个非常明确的设计目标。同时它也保证了产品的一致性。

  • 缺点

    • 当需要增加一类新的产品的时候,需要修改抽象工厂的接口,或者增加一个新的抽象工厂接口,这对于一个工厂而言是比较繁琐的。
  • 适用场景

    • 当需要创建一套产品对象,并且这些产品对象是相互依赖的,或者是从同一个产品族中创建出来的时候可以使用抽象工厂模式。
建造者模式(Builder)
  • 模式角色

    • 抽象建造者(Builder):为创建一个产品的各个部件指定抽象接口。

    • 具体建造者类(Concrete Builder):实现抽象接口,构建和装配各个部件。

    • 产品类(Product):通常是包含多个组成部件的复杂对象,由具体建造者来创建其各个部件。

    • 指挥者(Director):构建一个使用Builder接口的对象,指导建造过程。

  • 优点

    • 使得产品的内部表象可以独立地变化,客户端不必关心产品的组装方式和组成部分。

    • 建造者独立,易于扩展,符合开闭原则。

  • 缺点

    • 需要创建多个Builder对象以实现不同的产品,代码量较大。
  • 适用场景

    • 需要生成的产品具有复杂的内部结构,且可以由不同的部件组装而成时使用建造者模式。
原型模式(Prototype)
  • 模式角色

    • 抽象原型类(Prototype):定义了具体原型对象必须实现的接口。

    • 具体原型类(Concrete Prototype):实现了抽象原型类的clone()方法,完成对象的克隆。

  • 优点

    • 当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,提高创建新对象的效率,可以直接通过复制已有对象的方式来创建新对象。

    • 隐藏了对象创建的细节,客户端不需要知道创建对象细节。

  • 缺点

    • 部分语言不支持克隆操作(如PHP),需要自己手写克隆方法,增加代码复杂度。
  • 适用场景

    • 当需要创建新的对象实例较为复杂时,可以使用原型模式来简化对象创建过程。
单例模式(Singleton)
  • 模式角色

    • 单例类(Singleton):定义了一个getInstance()方法,允许客户端通过这个方法获取单例对象。
  • 优点

    • 在内存中只有一个对象,避免了频繁地创建与销毁对象,节省了系统资源。

    • 可以全局访问,方便进行对象的共享和协调工作。

  • 缺点

    • 违背了单一职责原则,一定程度上增加了代码的复杂度。

    • 单例对象如果持有过多的数据状态,容易导致对象状态不一致和线程安全等问题。

  • 适用场景

    • 当要求在系统中创建唯一对象,并且要求所有的客户端都能共享这个唯一对象时使用单例模式。

结构型模式

适配器模式(Adapter)
  • 模式角色

    • 目标接口(Target):定义客户端所需接口。

    • 适配器(Adapter):将原接口转换为目标接口的类,实现目标接口,调用原接口的方法来实现目标接口。

    • 源接口(Adaptee):需要被转换的原接口,但是与目标接口不一致。

  • 优点

    • 能够将原本不兼容的类组合在一起。

    • 提高了类的复用性。

  • 缺点

    • 过多使用适配器,会让系统变得复杂难懂。

    • 在实际项目中,如果使用不当,会给代码带来维护和扩展的难度。

  • 适用场景

    • 当需要使用的类的接口不符合当前项目的需求时,可以使用适配器模式进行对类的接口进行转换。
桥接模式(Bridge)
  • 模式角色

    • 抽象化(Abstraction):定义抽象类,并包含一个对实现化对象的引用。

    • 扩展抽象化(Refined Abstraction):扩展抽象化类,改变和修正父类对抽象化的定义。

    • 实现化(Implementor):定义实现化的接口,但不考虑具体实现。

    • 具体实现化(Concrete Implementor):提供实现化接口的具体实现。

  • 优点

    • 分离抽象与实现部分,扩展性强。

    • 对于不同的实现化角色,可以选择不同的具体实现化类,从而提高灵活性。

  • 缺点

    • 增加系统的理解和设计难度。
  • 适用场景

    • 当需要抽象化和实现化的角色分离时,可以使用桥接模式。此时,抽象化和实现化可以独立扩展,而不会相互影响。
装饰器模式(Decorator)
  • 模式角色

    • 抽象构件(Component):定义一个抽象接口,为需要装饰的对象定义出核心功能和基本操作。

    • 具体构件(Concrete Component):实现抽象构件角色所定义的的接口,即核心功能和基础操作。

    • 抽象装饰器(Decorator):维护一个指向抽象构件对象的引用,定义一个与抽象构件接口一致的接口。

    • 具体装饰器(Concrete Decorator):负责给构件对象添加额外的功能。

  • 优点

    • 可以动态地向对象添加功能,客户端可以在不需要知道对象具体实现的情况下,扩展对象功能。

    • 继承关系的代替方案,避免了动态继承的复杂性。

  • 缺点

    • 会增加许多子类,导致程序复杂。
  • 适用场景

    • 当需要对已有的对象进行功能增强时,可以使用装饰器模式。例如Java类库中的IO流。
外观模式(Facade)
  • 模式角色

    • 外观角色(Facade):为调用方定义简单易用的接口,隐藏了子系统的复杂性。

    • 子系统角色(Subsystem):实现外观角色定义的接口,在外观角色被调用时被活动。

  • 优点

    • 减少了系统的相互依赖,提高了灵活性。

    • 对客户屏蔽了系统的细节,方便客户端调用接口。

  • 缺点

    • 增加了系统的复杂性,不适合过度使用。
  • 适用场景

    • 当需要为子系统提供一个简单易用的接口并且需要隐藏子系统的复杂性时,可以使用外观模式。
享元模式(Flyweight)
  • 模式角色

    • 享元工厂(Flyweight Factory):工厂类,负责创建和管理享元对象。

    • 享元对象(Flyweight):维护一个内部状态和外部状态,内部状态是不可变的,而外部状态是每个对象不同的。

    • 非共享状态(Unshared Concrete Flyweight):不可以被共享的对象,通常需要满足多个条件才能被创建。

  • 优点

    • 通过共享对象减少内存中对象的数量,提高系统性能。

    • 可以减小系统中对象的数量,降低系统的复杂度,提高系统可维护性。

  • 缺点

    • 对象共享时,需要注意对象状态的安全问题。
  • 适用场景

    • 当需要大量的细粒度的对象,而内存空间有限时可以使用享元模式。

行为型模式

模板方法模式(Template Method)
  • 模式角色

    • 抽象类(Abstract Class):定义抽象的模板方法以及一些基本的操作和抽象方法,具体的子类可以进行改写。

    • 具体类(Concrete Class):实现抽象类中的抽象方法,在模板方法中调用这些具体方法实现算法流程。

  • 优点

    • 提供通用的代码,可以避免重复的代码。

    • 定义了一个算法流程,具体实现可以在子类中完成,提高了代码的扩展性。

  • 缺点

    • 可能会对具体实现类的维护带来麻烦。

    • 由于采用了继承机制,某些类内部实现没法修改而导致可能会出现一定的安全性问题。

  • 适用场景

    • 当多个类有相似的操作时,可以使用模板方法模式将这些操作抽象出来,由子类实现。
策略模式(Strategy)
  • 模式角色

    • 抽象策略类(Strategy):定义一个抽象的策略接口。

    • 具体策略类(Concrete Strategy):实现抽象策略接口,完成具体的策略算法。

    • 环境类(Context):持有一个策略类的引用,它用于传递客户端的请求给具体的策略类。

  • 优点

    • 可以在运行时根据需要替换算法,动态地将具体策略类注入到环境类中。

    • 策略类之间可以自由切换。

  • 缺点

    • 客户端必须知道不同的策略算法之间的区别,才能选择合适的算法。
  • 适用场景

    • 当需要在不同的算法中进行切换时,可以使用策略模式。
命令模式(Command)
  • 模式角色

    • 抽象命令类(Command):定义了一个命令的接口,包含了命令执行的方法。

    • 具体命令类(Concrete Command):实现抽象命令类中的抽象方法,在对应的接收者类中完成具体命令操作。

    • 接收者类(Receiver):真正执行具体命令操作,具体命令对象需要和接收者相关联。

    • 调用者(Invoker):负责调用具体命令类的执行方法执行命令操作,还可以记录执行命令的日志。

  • 优点

    • 可以将请求者(Invoker)与接收者(Receiver)解耦,实现请求者与接收者之间的解耦。

    • 命令类是一种对象,可以方便的进行扩展和修改。

  • 缺点

    • 会增加系统的类和对象数量。
  • 适用场景

    • 当需要将请求者与接收者解耦时,可以使用命令模式。
职责链模式(Chain of Responsibility)
  • 模式角色

    • 抽象处理者(Handler):定义了抽象的处理请求的接口。

    • 具体处理者(Concrete Handler):实现抽象处理者接口,并完成实际的处理逻辑。如果不能处理请求,将请求转发给下一个处理者。

    • 请求者(Requestor):向职责链发起请求,并不知道是哪个处理者处理请求的。

    • 职责链(Chain):存储处理者对象,并负责转发请求给处理者。

  • 优点

    • 将请求和处理者解耦,增强系统的灵活性。

    • 可以在运行时动态添加/删除处理者。

    • 可以将一些繁琐的、重复的逻辑都放在处理者中,提高代码的复用性。

  • 缺点

    • 当职责链过长时,可能会导致性能问题。
  • 适用场景

    • 当有多个对象可以处理同一个请求时,可以使用职责链模式,以减少请求的发送者和接收者之间的耦合。
迭代器模式(Iterator)
  • 模式角色

    • 抽象迭代器(Iterator):定义了访问和遍历元素的接口。

    • 具体迭代器(Concrete Iterator):实现了抽象迭代器接口,并完成对应的具体遍历操作。

    • 抽象聚合类(Aggregate):定义创建迭代器对象的接口,也就是创建一个可以遍历聚合内部元素的迭代器。

    • 具体聚合类(Concrete Aggregate):实现抽象聚合类接口,并用于创建具体迭代器。其内部存储元素,可以被迭代器遍历。

  • 优点

    • 让聚合对象和遍历逻辑分离,简化了聚合对象的实现。

    • 可以提供多种不同的遍历方式。

  • 缺点

    • 如果遍历方式过于复杂,实现起来可能会比较麻烦。
  • 适用场景

    • 当需要遍历一个聚合对象,并且需要提供不同的遍历方式时,可以使用迭代器模式。
观察者模式(Observer)
  • 模式角色

    • 抽象主题(Subject):定义了观察者要注册和注销的方法,以及通知观察者的方法。

    • 具体主题(Concrete Subject):实现了抽象主题角色中定义的方法,并可以被具体的观察者所订阅。

    • 抽象观察者(Observer):定义了接收主题通知的方法。

    • 具体观察者(Concrete Observer):实现了抽象观察者接口,用于被主题通知更新。

  • 优点

    • 可以实现对象间的松耦合。

    • 可以让观察者根据自己的具体需要,自由地订阅与取消订阅。

  • 缺点

    • 如果主题对象和观察者对象之间存在复杂的依赖关系,可能会导致代码难以维护。
  • 适用场景

    • 当一个对象的状态发生改变时,需要让其他相关对象也随之做出相应的动作时,可以使用观察者模式。#### 中介者模式(Mediator)
  • 模式角色

    • 抽象中介者(Mediator):定义了中介者处理消息的接口,和注册和删除同事对象的方法。

    • 具体中介者(Concrete Mediator):实现抽象中介者接口,并负责协调各个同事对象之间的通信。

    • 抽象同事类(Colleague):定义了需要与其他同事对象通信的接口。

    • 具体同事类(Concrete Colleague):实现抽象同事类接口,并与其他同事类进行通信。

  • 优点

    • 降低系统中对象之间的耦合度。

    • 中介者模式将多个对象之间的交互集中在中介者中进行,便于系统维护和扩展。

  • 缺点

    • 中介者模式会增加系统中的对象数量,可能会使得系统变得复杂。
  • 适用场景

    • 当多个对象之间存在复杂的相互依赖关系,可以使用中介者模式。
访问者模式(Visitor)
  • 模式角色

    • 抽象访问者(Visitor):定义了访问不同类型元素所需要实现的方法。

    • 具体访问者(Concrete Visitor):实现抽象访问者接口,并访问具体元素。

    • 抽象元素(Element):定义了接收访问者访问的接口。

    • 具体元素(Concrete Element):实现抽象元素接口,并实现不同类型元素的访问方法。

    • 对象结构(Object Structure):用于管理元素对象的集合,并可以遍历这些元素对象,并调用对应的访问者的方法进行访问。

  • 优点

    • 增加新的操作或者访问数据结构中的元素,只需要添加新的具体访问者或者具体元素,不会影响到现有的代码。

    • 访问者模式可以将数据结构与算法解耦,使得数据结构和算法可以独立地变化。

  • 缺点

    • 访问者模式增加了系统的复杂度,需要对元素和访问者进行分类管理。
  • 适用场景

    • 当待操作的数据结构比较稳定,但是经常需要在此数据结构上定义新的操作,可以使用访问者模式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值