开发者设计模式

设计模式是在软件设计中常见的可复用解决方案的一种用法模板。以下是30个常见的设计模式、对应的应用场景、现实例子以及优缺点:

1. 单例模式(Singleton):
应用场景:当只需要一个全局实例时。
现实例子:操作系统的文件系统。
优点:节省了系统资源,避免了不必要的实例化。
缺点:可测试性差,扩展性差。

2. 工厂模式(Factory):
应用场景:在创建对象时需要根据条件返回不同类型的实例。
现实例子:汽车制造工厂。
优点:封装了对象的创建过程,降低了耦合性。
缺点:当需要添加新的产品类型时,需要修改工厂类。

3. 抽象工厂模式(Abstract Factory):
应用场景:需要创建一组相关或依赖的对象。
现实例子:游戏中的角色创建。
优点:隐藏了具体实现,客户端可以通过抽象接口操纵对象。
缺点:增加新产品族时不容易,需要修改抽象工厂接口。

4. 建造者模式(Builder):
应用场景:创建复杂对象的步骤较多,需要一步一步创建。
现实例子:房屋施工过程。
优点:将对象的构建过程与表示分离,使得构建过程灵活可变。
缺点:可能需要创建多个具体构建器。

5. 原型模式(Prototype):
应用场景:需要生成大量拥有相同属性的对象。
现实例子:公共自行车租赁系统。
优点:避免了重复创建相似对象的开销。
缺点:如果对象有复杂的初始化过程,使用原型模式可能并不方便。

6. 适配器模式(Adapter):
应用场景:需要将一个类的接口转换为另一个类的接口。
现实例子:充电器适配器。
优点:将不兼容的接口转换为兼容接口,提高了代码的复用性。
缺点:增加了代码的复杂性。

7. 桥接模式(Bridge):
应用场景:将抽象部分与实现部分分离,使它们可以独立变化。
现实例子:操作系统与文件系统的桥接。
优点:抽象和实现的分离,易于扩展。
缺点:增加了系统的复杂性。

8. 组合模式(Composite):
应用场景:需要树状结构表示对象的部分-整体关系。
现实例子:文件系统的目录和文件。
优点:简化了客户端代码,容易添加新的组件。
缺点:限制了组合中各个组件的类型。

9. 装饰者模式(Decorator):
应用场景:需要动态地为对象添加额外的功能。
现实例子:咖啡店中的配料选择。
优点:可以动态地为对象添加新的功能。
缺点:增加了代码的复杂性。

10. 外观模式(Facade):
应用场景:将复杂的子系统封装为一个简单的接口。
现实例子:电脑开机的启动流程。
优点:简化了客户端的操作,减少了对子系统的直接调用。
缺点:不符合开闭原则,对子系统的修改可能需要修改外观类。

11. 享元模式(Flyweight):
应用场景:需要共享对象以减少内存占用的情况。
现实例子:池技术的使用。
优点:减少了对象的创建和销毁,降低了内存的使用。
缺点:需要维护共享对象池,增加了复杂性。

12. 代理模式(Proxy):
应用场景:需要在访问对象之前进行一些额外的操作。
现实例子:远程调用。
优点:可以在访问对象时做一些额外的处理。
缺点:增加了代码的复杂性。

13. 模板方法模式(Template Method):
应用场景:在算法的骨架中有一些确定的步骤,但是具体的实现可以有所不同。
现实例子:咖啡和茶的冲泡过程。
优点:将算法的通用部分抽象为模板方法,将具体实现交给子类。
缺点:可能导致继承滥用。

14. 策略模式(Strategy):
应用场景:需要根据不同的算法来选择不同的处理方式。
现实例子:支付方式的选择。
优点:可以动态地切换策略,减少了条件语句的使用。
缺点:增加了类的数量。

15. 状态模式(State):
应用场景:需要根据对象的状态来改变其行为。
现实例子:交通信号灯,遥控按钮,将方法封装成类。
优点:将状态的处理逻辑封装在状态类中,易于理解和维护。
缺点:可能导致处理过程的碎片化。

16. 观察者模式(Observer):
应用场景:需要实现对象之间的一对多的依赖关系。
现实例子:消息订阅系统。
优点:解耦了观察者和被观察者,易于扩展。
缺点:可能导致循环引用。

17. 中介者模式(Mediator):
应用场景:需要解耦多个对象之间的复杂关系。
现实例子:聊天室中的消息中转。
优点:将多个对象之间的通信集中在中介者中,简化了系统的复杂性。
缺点:可能导致中介者类变得庞大复杂。

18. 备忘录模式(Memento):
应用场景:需要保存对象的内部状态,以便之后能够恢复到原始状态。
现实例子:文字处理软件中的撤销功能。
优点:封装了对象内部状态的保存和恢复逻辑,简化了客户端代码。
缺点:可能导致资源的消耗过大。

19. 解释器模式(Interpreter):
应用场景:需要解释和执行一些简单的语言规则。
现实例子:数据库查询语言,数学公式编辑器。
优点:易于扩展和修改语言规则。
缺点:语义解释可能较为复杂。

20. 命令模式(Command):
应用场景:需要将方法调用封装成对象以进行参数化。
现实例子:遥控器的按钮。
优点:将方法调用解耦,支持撤销和重做操作。
缺点:增加了类的数量。

21. 访问者模式(Visitor):
应用场景:需要在不改变元素类的情况下,为其添加新的操作。
现实例子:电影票价格计算器。
优点:将操作和元素分离,易于增加新的操作。
缺点:增加了代码的复杂性和访问者类的数量。

22. 责任链模式(Chain of Responsibility):
应用场景:需要将请求的发送者和接收者解耦。
现实例子:事件的传递和处理链。
优点:解耦了请求的发送者和接收者,可以动态地修改链条的结构。
缺点:可能导致请求被忽略或循环引用。

23. 迭代器模式(Iterator):
应用场景:需要遍历一个聚合对象。
现实例子:迭代器模式。
优点:封装了聚合对象的遍历过程,提供了不同遍历方式。
缺点:增加了复杂性。

24. 双重检查锁定模式(Double Check Locking)
应用场景:在多线程环境下确保懒加载对象的线程安全。
现实例子:单例模式的多线程情况下的实现。
优点:线程安全,同时又能保持对象的懒加载特性。
缺点:通过双重检查来实现线程安全增加了复杂性。

25. 读写锁模式(Read Write Lock)
应用场景:在读多写少的情况下提高程序的并发性能。
现实例子:数据库的并发访问。
优点:提高了程序的并发性能,加快了读操作的速度。
缺点:增加了代码的复杂性,同时也存在死锁的风险。

26. 保护代理模式(Protection Proxy)
应用场景:在访问对象之前进行身份验证和权限检查。
现实例子:网络安全防火墙。
优点:增加了代码的安全性,提高了系统的稳定性。
缺点:可能导致访问效率的降低。

27. 动态代理模式(Dynamic Proxy)
应用场景:在运行时为对象动态生成代理类。
现实例子:AOP框架中的动态代理功能。
优点:避免了静态代理中需要手动编写代理类的复杂性。
缺点:增加了运行时的开销。

28. 生成器模式(Generator)
应用场景:需要按照一定的步骤生成复杂对象。
现实例子:代码生成器。
优点:将复杂对象的创建步骤分离,易于扩展和维护。
缺点:可能导致生成器类变得庞大复杂。

29. 采购审批流程设计模式
应用场景:需要设计采购审批流程,实现权限控制和流程控制。
现实例子:企业的采购流程。
优点:使采购流程形式化、规范化,提高效率和质量。
缺点:当流程变更时,可能需要修改较多的代码。 

30. 委托模式(Delegation Pattern)

应用场景:需要将某个操作委托给其他对象来完成,可以使用委托模式。
优点:将对象之间的逻辑关系解耦,提高了系统的灵活性和可扩展性。
缺点:需要额外的委托对象。

31. 门面模式(Facade Pattern)
应用场景:需要为一组复杂的子系统提供一个简单的接口,可以使用门面模式。
优点:减少了客户端与子系统之间的依赖关系,提高了系统的易用性。
缺点:违反了单一职责原则,增加了门面类的复杂性。

32. 多态模式(Polymorphism Pattern)
应用场景:需要根据使用对象的类型来决定具体的行为时,可以使用多态模式。
优点:提高了代码的可读性和可维护性,增强了程序的扩展性。
缺点:需要正确地定义和使用父类和子类之间的接口。

33. 模式的高阶使用
模式也可以组合使用,以实现更复杂的功能。比如结合使用观察者模式和策略模式,以实现根据不同的策略动态地添加和移除观察者。

37. 接口隔离原则(Interface Segregation Principle)
应用场景:需要将复杂的接口进行拆分,以便于不同的类只需要实现自己所需要的接口方法,可以使用接口隔离原则。
优点:减少了类之间的依赖关系,提高了系统的内聚性。
缺点:增加了系统的复杂性,需要合理地设计和管理接口。

38. 依赖倒置原则(Dependency Inversion Principle)
应用场景:需要降低模块或类之间的耦合度,可以使用依赖倒置原则。
优点:提高了代码的可读性和可维护性,增强了系统的扩展性。
缺点:增加了系统的复杂性,需要合理地设计和管理依赖关系。

39. 开闭原则(Open-Closed Principle)
应用场景:当需要在系统中添加新功能时,应该通过扩展现有的代码来实现,而不是修改已经存在的代码。这样可以避免因修改已有代码而引入新的bug。
例子:图形绘制软件,在该软件中有多种形状(如圆、矩形、三角形等)需要进行绘制。如果每次添加一个新形状都需要修改原有的绘制逻辑,那么每次修改都会引入潜在的风险。而如果使用开闭原则,可以通过新增一个绘制接口,并根据不同的形状分别实现该接口,从而在不修改原有代码的基础上扩展新的形状
优点:封装性好:可以将变化隔离在新的扩展中,不需要修改已有的代码,从而提高代码的可维护性和可复用性。
可扩展性强:通过扩展现有代码,可以很容易地添加新的功能,满足不断变化的需求。
缺点:需要额外的设计和编码工作:使用开闭原则需要对系统进行设计,需要提前预留扩展点,并进行相应的编码工作。这可能会增加一些工作量。
可能导致过度设计:在使用开闭原则时,需要做好合适的抽象和封装,避免过度设计。否则可能会导致代码过于复杂,难以理解和维护。

posted @ 2023-07-04 08:18  专注视觉  阅读(50)  评论(0编辑  收藏  举报