首页 > 其他分享 >策略模式和适配器模式

策略模式和适配器模式

时间:2024-10-26 18:19:08浏览次数:6  
标签:策略 适配器 接口 算法 模式 self

好的,让我们从设计模式的角度深入分析策略模式(Strategy Pattern)适配器模式(Adapter Pattern),探讨它们的区别、应用场景以及各自的设计意图。

一、策略模式(Strategy Pattern)

1. 定义

策略模式是一种行为型设计模式,它定义了一系列算法,把它们一个个封装起来,并且使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户端。

2. 组成部分

  • 策略接口(Strategy Interface):定义了一个算法族的公共接口。
  • 具体策略(Concrete Strategy):实现了策略接口的具体算法。
  • 上下文(Context):持有一个策略接口的引用,客户端可以通过上下文来设置具体的策略。

3. 设计意图

  • 封装变化:将不同的算法封装在不同的策略类中,使得算法可以独立于客户端变化。
  • 简化复杂性:通过将算法的实现细节封装在策略类中,上下文类只需要知道如何使用策略接口即可,减少了类之间的耦合。
  • 提高灵活性:可以在运行时动态地改变策略,实现行为的动态变化。

4. 应用场景

  • 多种算法的选择:当系统需要在多种算法中选择一种来完成某项功能时。
  • 算法独立变化:当算法经常变化,且需要独立于使用算法的客户端变化时。
  • 简化条件语句:用不同的策略替代冗长的条件语句,使代码更加清晰。

5. 示例

假设有一个文本编辑器,支持不同的文本格式(如纯文本、Markdown、HTML)的导出。可以使用策略模式来封装不同的导出算法。

from abc import ABC, abstractmethod

# 策略接口
class ExportStrategy(ABC):
    @abstractmethod
    def export(self, content: str) -> str:
        pass

# 具体策略
class PlainTextExportStrategy(ExportStrategy):
    def export(self, content: str) -> str:
        return content

class MarkdownExportStrategy(ExportStrategy):
    def export(self, content: str) -> str:
        return f"# {content}"

class HTMLExportStrategy(ExportStrategy):
    def export(self, content: str) -> str:
        return f"<h1>{content}</h1>"

# 上下文
class TextEditor:
    def __init__(self, strategy: ExportStrategy):
        self.strategy = strategy
        self.content = ""

    def set_strategy(self, strategy: ExportStrategy):
        self.strategy = strategy

    def write(self, text: str):
        self.content += text

    def export(self) -> str:
        return self.strategy.export(self.content)

# 使用示例
editor = TextEditor(PlainTextExportStrategy())
editor.write("Hello, World!")
print(editor.export())  # 输出: Hello, World!

editor.set_strategy(MarkdownExportStrategy())
print(editor.export())  # 输出: # Hello, World!

editor.set_strategy(HTMLExportStrategy())
print(editor.export())  # 输出: <h1>Hello, World!</h1>

二、适配器模式(Adapter Pattern)

1. 定义

适配器模式是一种结构型设计模式,它允许将一个类的接口转换成客户端所期望的另一种接口。适配器模式使得原本由于接口不兼容而无法一起工作的类可以一起工作。

2. 组成部分

  • 目标接口(Target Interface):客户端所期望的接口。
  • 源接口(Adaptee):需要适配的接口。
  • 适配器(Adapter):通过包装源接口,实现目标接口。

3. 设计意图

  • 接口兼容:解决接口不兼容的问题,使得原本不兼容的类可以协同工作。
  • 复用现有类:在不修改现有类的情况下,使用其功能。
  • 简化接口:通过适配器,可以对复杂接口进行简化,使其更易于使用。

4. 应用场景

  • 接口不兼容:当需要使用一个现有类,但其接口不符合需求时。
  • 复用现有类:需要使用第三方库或遗留系统中的类,但接口不一致时。
  • 增强功能:在不修改现有类的基础上,增加新的功能。

5. 示例

假设有一个应用程序需要使用一个图形接口(绘制圆形),但现有的类只能绘制椭圆。通过适配器模式,可以将椭圆类适配成圆形接口。

from abc import ABC, abstractmethod

# 目标接口
class Shape(ABC):
    @abstractmethod
    def draw_circle(self, radius: float):
        pass

# 源接口
class Ellipse:
    def draw_ellipse(self, h_radius: float, v_radius: float):
        print(f"Drawing ellipse with horizontal radius {h_radius} and vertical radius {v_radius}")

# 适配器
class EllipseAdapter(Shape):
    def __init__(self, ellipse: Ellipse):
        self.ellipse = ellipse

    def draw_circle(self, radius: float):
        # 将圆形转换为椭圆(水平和垂直半径相同)
        self.ellipse.draw_ellipse(radius, radius)

# 使用示例
ellipse = Ellipse()
circle_adapter = EllipseAdapter(ellipse)
circle_adapter.draw_circle(5)  # 输出: Drawing ellipse with horizontal radius 5 and vertical radius 5

三、策略模式与适配器模式的区别与联系

1. 设计意图

  • 策略模式:封装不同的算法或策略,允许在运行时动态切换,实现行为的可变性和灵活性。
  • 适配器模式:使不兼容的接口能够协同工作,通过封装已有类,实现接口转换。

2. 结构不同

  • 策略模式
    • 核心:算法族的封装和切换。
    • 依赖关系:上下文依赖于策略接口,策略实现具体算法。
  • 适配器模式
    • 核心:接口转换。
    • 依赖关系:客户端依赖于目标接口,适配器依赖于源接口和目标接口,实现接口的兼容。

3. 应用场景不同

  • 策略模式
    • 当需要在多个算法中选一个时,可以使用策略模式。
    • 适用于需要动态切换算法或行为的场景。
  • 适配器模式
    • 当需要使用一个已有类,但其接口不符合要求时,可以使用适配器模式。
    • 适用于需要复用现有类库、集成遗留系统或第三方服务的场景。

4. 联系

  • 都是封装变动的设计模式,通过封装内部实现,提供统一的外部接口。
  • 都提高了系统的灵活性可扩展性,减少了类之间的耦合。

5. 示例对比

策略模式示例
  • 场景:文本编辑器支持多种导出格式(如纯文本、Markdown、HTML)。
  • 目标:动态选择和切换导出算法。
适配器模式示例
  • 场景:应用程序需要使用一个只能绘制椭圆的类来绘制圆形。
  • 目标:通过适配器,实现绘制圆形的接口兼容。

四、总结

策略模式

  • 目的:封装算法,允许动态切换和扩展。
  • 使用场景:需要在多种算法中选择一种,或需要动态改变对象的行为。
  • 优点
    • 高内聚,低耦合。
    • 易于扩展新的策略。
    • 避免使用大量的条件语句。
  • 缺点
    • 客户端必须理解不同策略的区别。

适配器模式

  • 目的:解决接口不兼容的问题,使不同接口的类能够协同工作。
  • 使用场景:需要使用一个已有类,但其接口不符合需求,或需要集成第三方库。
  • 优点
    • 提高了类的复用性。
    • 隐藏了不兼容接口的复杂性。
  • 缺点
    • 可能增加系统的复杂性。
    • 如果系统中有大量的适配器,可能导致维护困难。

选择建议

  • 选择策略模式:当关注点是算法的封装和动态切换,且算法之间具有相同的接口时。
  • 选择适配器模式:当需要让现有类与新接口兼容,或集成不兼容的系统组件时。

理解并正确应用这些设计模式,可以让您的系统更加灵活、可维护,并且易于扩展。希望以上分析对您有所帮助!

标签:策略,适配器,接口,算法,模式,self
From: https://blog.csdn.net/u011027104/article/details/143111869

相关文章

  • springboot 实现通用责任链模式
    1.概述在我们平时的工作中,填写分布填写数据,比如填入商品的基本信息,所有人信息,明细信息,这种情况就可以使用责任链模式来处理。2.代码实现2.1商品对象publicclassProductDto{privateStringname;privateStringowner;privateStringdetail;}2.2处理......
  • 《大话设计模式》java实现:第二章-策略模式
    《大话设计模式》java实现:第二章-策略模式第二章是使用策略模式实现商场收银系统,使收银系统的促销策略可以灵活更改。1.原始代码实现:packagegof;/**《大话设计模式》第二章策略模式*实现商场收银系统,可以选择不同促销策略*/importjavax.swing.*;importjava.aw......
  • 【算法优化】混合策略改进的蝴蝶优化算法
    摘要蝴蝶优化算法(ButterflyOptimizationAlgorithm,BOA)是一种新兴的智能优化算法,其灵感来自蝴蝶的觅食行为。本文基于经典BOA,通过引入混合策略进行改进,从而提高其在全局寻优和局部搜索中的性能。实验结果表明,改进的蝴蝶优化算法(IBOA)在处理复杂多模态函数优化问题时表......
  • 线程池与拒绝策略
    在Java中,ThreadPoolExecutor是线程池的核心实现类,它提供了丰富的配置选项和拒绝策略,用于高效管理线程的执行。线程池的七个参数和拒绝策略是线程池工作机制的重要组成部分,下面将详细解释它们的作用。1.线程池的七个参数ThreadPoolExecutor的构造函数包含七个关键参数......
  • SLF4J 中的单例模式
    基于:SLF4J框架源码中是如何实现双重锁的?当我们使用SLF4J时,通常通过如下代码获取对应的Logger:Loggerlogger=LoggerFactory.getLogger(NoBindingTest.class);在LoggerFactory的getLogger方法中,最主要的功能就是获得Logger,获得Logger需要先获得对应的ILoggerFac......
  • 基于CLIP的关键帧选择策略
    基于CLIP的关键帧选择策略:原理这种方法将整个视频划分为多个片段(clips),并从每个片段中提取能够代表该片段的关键帧。具体过程如下:使用CLIP提取特征:第一步是使用CLIP模型对视频的第一帧进行编码,生成特征向量,该向量包含了该帧的高级语义信息。CLIP能够将图像的视觉内容压缩为......
  • Java 单例模式
    原文:Java单例模式的7种写法中,为何用Enum枚举实现被认为是最好的方式?1、懒汉(线程不安全)publicclassSingleton{privatestaticSingletoninstance;privateSingleton(){}//私有构造函数publicstaticSingletongetInstance(){if(insta......
  • SLF4J 中的适配器模式
    什么是适配器模式适配器模式中,适配器包装不兼容指定接口的对象,来实现不同兼容指定接口。SLF4J中的适配器模式SLF4J是一个日志门面系统,其中提供了统一的Logger等接口,许多框架都会面向SLF4J打印日志,这样就不会和具体的日志框架耦合在一起,框架使用者也就能够很方便地在不同......
  • 前端开发设计模式——工厂模式
    目录一、定义和特点1.定义2.特点二、实现方式三、使用场景1.创建复杂对象2.根据不同条件创建对象四、优点1.代码复用2.解耦对象创建和使用3.易于维护五、缺点1.增加代码复杂度2.工厂函数可能变得臃肿六、注意事项1.命名规范2.单一职责原则3.错误......
  • 工厂设计模式
    工厂设计模式工厂设计模式是一种创建型设计模式,它提供了一种创建对象的最佳方式,工厂模式的核心是定义一个创建对象的接口,但是让实现这个接口的类来决定实例化哪一个类。工厂模式将实例化的过程延迟到子类中进行。类型:工厂设计模式有不同的变种,其中包括:简单工厂模式:由一个工厂......