首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何重构切换用例,以便我可以扩展这些用例,并在不同的类中添加另一个用例?

重构切换用例以便于扩展和维护是一个常见的软件设计任务。以下是一些基础概念和相关策略,帮助你实现这一目标:

基础概念

  1. 单一职责原则(Single Responsibility Principle, SRP):一个类应该只有一个引起它变化的原因。
  2. 开闭原则(Open/Closed Principle, OCP):软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
  3. 依赖倒置原则(Dependency Inversion Principle, DIP):高层模块不应该依赖低层模块,两者都应该依赖抽象;抽象不应该依赖细节,细节应该依赖抽象。

相关优势

  • 可扩展性:新增功能时不需要修改现有代码。
  • 可维护性:代码结构清晰,易于理解和维护。
  • 可测试性:更容易编写单元测试,隔离各个组件。

类型与应用场景

使用策略模式(Strategy Pattern)

类型:行为设计模式。

应用场景:当一个系统需要动态地在几种算法中选择一种时,可以将每个算法封装到策略类中。

使用工厂模式(Factory Pattern)

类型:创建型设计模式。

应用场景:当一个类不知道它所需要的对象的类,或者一个类通过其子类来指定创建对象时。

示例代码

假设我们有一个简单的切换用例系统,现在需要扩展这些用例并在不同的类中添加新的用例。

原始代码

代码语言:txt
复制
class SwitchCase:
    def execute(self):
        if self.case == 'A':
            self.handle_case_a()
        elif self.case == 'B':
            self.handle_case_b()

    def handle_case_a(self):
        print("Handling case A")

    def handle_case_b(self):
        print("Handling case B")

重构后的代码

使用策略模式重构:

代码语言:txt
复制
from abc import ABC, abstractmethod

# 定义策略接口
class SwitchStrategy(ABC):
    @abstractmethod
    def execute(self):
        pass

# 具体策略A
class CaseAStrategy(SwitchStrategy):
    def execute(self):
        print("Handling case A")

# 具体策略B
class CaseBStrategy(SwitchStrategy):
    def execute(self):
        print("Handling case B")

# 上下文类,用于切换策略
class SwitchContext:
    def __init__(self, strategy: SwitchStrategy):
        self._strategy = strategy

    def set_strategy(self, strategy: SwitchStrategy):
        self._strategy = strategy

    def execute_strategy(self):
        self._strategy.execute()

# 使用示例
if __name__ == "__main__":
    context = SwitchContext(CaseAStrategy())
    context.execute_strategy()  # 输出: Handling case A

    context.set_strategy(CaseBStrategy())
    context.execute_strategy()  # 输出: Handling case B

解决问题的方法

  1. 识别重复代码:找出代码中重复的部分,将其抽象成独立的类或函数。
  2. 引入接口或抽象类:定义一个统一的接口或抽象类,让不同的用例实现这个接口。
  3. 使用依赖注入:通过构造函数或setter方法将具体策略注入到上下文类中,而不是在上下文类内部创建具体策略实例。

遇到问题的原因及解决方法

问题:新增用例时需要修改现有代码。

原因:违反了开闭原则,系统对修改开放。

解决方法:使用设计模式(如策略模式)将每个用例封装成独立的策略类,通过上下文类动态切换策略,从而避免修改现有代码。

通过上述方法,你可以有效地重构切换用例,使其更具扩展性和可维护性。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

「首席看软件架构」DDD,六边形,洋葱的,干净的,CQRS的整合架构

例如,在CMS中,我们可以有普通用户使用的实际应用程序UI、CMS管理员使用的另一个独立UI、另一个CLI UI和web API。这些ui(应用程序)可以触发特定于其中一个或由其中几个重用的用例。...命令处理程序可以用两种不同的方式使用: 它们可以包含执行用例的实际逻辑; 它们可以在我们的体系结构中用作简单的连接块,接收命令并简单地触发存在于应用程序服务中的逻辑。...这一层还包含应用程序事件的触发,这些事件表示用例的一些结果。这些事件触发的逻辑是用例的副作用,比如发送电子邮件、通知第三方API、发送推送通知,甚至启动属于应用程序不同组件的另一个用例。...此外,如果我们有一个多语言系统,假设是一个微服务生态系统,其中它们是用不同的语言编写的,那么共享内核需要是语言无关的,以便所有组件都可以理解它,无论它们是用什么语言编写的。...这就是我在脑海里给它找的合理解释。 我在后续的文章中进一步扩展了这些想法:不仅仅是同心圆层。 但是,我们如何在代码库中显式地实现这一切呢?这是我下一篇文章的主题:如何在代码中反映体系结构和域。

5.2K22

【总结】1773- 前端简洁架构

在这篇文章中,我将概述那次演讲,并对其进行了一些扩展。 我在这里附了一些含有不错的内容的链接,这些对后续的阅读会有一些帮助。...即使我们跳过了其他的层,也会更容易使用提取出来的领域进行工作和重构,因为它并没有分布在代码库中。其他层可以根据需要添加。...我建议你从领域开始,以便在你的代码中准确地表达应用程序的领域知识。 商店领域可能包括: 实体的数据类型:用户、cookie、购物车和订单。 创建实体的工厂,如果你用OOP编写,则是类。...在选择不同的实体和扩展时,使用BEM中的块和修饰符类比。当我在BEM的上下文中考虑时,它对我在确定是否有一个单独的实体或者一个“修饰符扩展”代码时非常有帮助。...相互依赖的用例 第二个重要的问题涉及到使用用例,其中一个用例的事件触发另一个用例。 我所知道和帮助我的处理方式是将用例拆分为更小、原子化的用例。这样它们将更容易组合在一起。

24530
  • 「领域驱动设计」DDD,六边形架构,洋葱架构,整洁架构,CQRS的整合架构

    这篇文章是软件架构编年史的一部分,一系列关于软件架构的文章。在这些文章中,我写了我对软件架构的了解,我如何看待它,以及我如何使用这些知识。如果您阅读了本系列以前的文章,那么本文的内容可能更有意义。...例如,在CMS中,我们可以有普通用户使用的实际应用程序UI、CMS管理员使用的另一个独立UI、另一个CLI UI和web API。这些ui(应用程序)可以触发特定于其中一个或由其中几个重用的用例。...命令处理程序可以用两种不同的方式使用: 它们可以包含执行用例的实际逻辑; 它们可以在我们的体系结构中用作简单的连接块,接收命令并简单地触发存在于应用程序服务中的逻辑。...这一层还包含应用程序事件的触发,这些事件表示用例的一些结果。这些事件触发的逻辑是用例的副作用,比如发送电子邮件、通知第三方API、发送推送通知,甚至启动属于应用程序不同组件的另一个用例。...这就是我在脑海里给它找的合理解释。 我在后续的文章中进一步扩展了这些想法:不仅仅是同心圆层。 但是,我们如何在代码库中显式地实现这一切呢?这是我下一篇文章的主题:如何在代码中反映体系结构和域。

    2K30

    什么是前端简洁架构

    在这篇文章中,我将概述那次演讲,并对其进行了一些扩展。 我在这里附了一些含有不错的内容的链接,这些对后续的阅读会有一些帮助。...即使我们跳过了其他的层,也会更容易使用提取出来的领域进行工作和重构,因为它并没有分布在代码库中。其他层可以根据需要添加。...我建议你从领域开始,以便在你的代码中准确地表达应用程序的领域知识。 商店领域可能包括: 实体的数据类型:用户、cookie、购物车和订单。 创建实体的工厂,如果你用OOP编写,则是类。...在选择不同的实体和扩展时,使用BEM中的块和修饰符类比。当我在BEM的上下文中考虑时,它对我在确定是否有一个单独的实体或者一个“修饰符扩展”代码时非常有帮助。...相互依赖的用例 第二个重要的问题涉及到使用用例,其中一个用例的事件触发另一个用例。 我所知道和帮助我的处理方式是将用例拆分为更小、原子化的用例。这样它们将更容易组合在一起。

    39720

    Swift 中风味各异的依赖注入

    前言 在之前的文章中,我们看了一些使用依赖注入的不同方法,以实现Swift应用中更多的解耦和可测试架构。...本周,让我们来看看三种不同方式的依赖注入,以及它们如何在Swift中使用。...这种方式的最大好处是,它保证我们的对象拥有它们所需要的一切,以便立即开展工作。 假设我们正在构建一个从磁盘上加载文件的FileLoader。...Swift 代码"*中的技术是如何通过使用协议来为系统照片库类提供一个更抽象的PhotoLibrary接口。...这几乎可以让我们在测试中把上述API变成一个同步的API,这让事情变得更容易和更可预测。 基于参数的依赖注入的另一个用例是当你想测试静态API的时候。

    67910

    Swift 中风味各异的依赖注入

    在之前的文章中,我们看了一些使用依赖注入的不同方法,以实现Swift应用中更多的解耦和可测试架构。...本周,让我们来看看三种不同方式的依赖注入,以及它们如何在Swift中使用。...这种方式的最大好处是,它保证我们的对象拥有它们所需要的一切,以便立即开展工作。 假设我们正在构建一个从磁盘上加载文件的FileLoader。...Swift 代码"中的技术是如何通过使用协议来为系统照片库类提供一个更抽象的PhotoLibrary接口。...这几乎可以让我们在测试中把上述API变成一个同步的API,这让事情变得更容易和更可预测。 基于参数的依赖注入的另一个用例是当你想测试静态API的时候。

    81810

    如何测试复杂的逻辑

    业务的规则和验证占据了客户提供的需求的很大一部分。当我们观察这些需求是如何通过业务分析师或客户来表达和传达给整个项目团队的时候,我们就会知道大多数这样的业务规则和逻辑是以一个逻辑程序流程图来表达的。...,并且可以在编写测试用例时包括在内 在完成决策表之后,只需要验证逻辑树中的所有分支和叶子是否都被覆盖 使用决策表技术的优点 用图表示的任何复杂的业务流程都可以很容易地用这种技术覆盖 它提供了测试用例的信心...但是,可以在组合列中记下它,并在编写测试用例时使用它们 在解释为什么其他测试用例编写技术不能像决策表那样保证准确性之前,我想快速地提醒其他黑盒和白盒测试用例编写技术。...这两种技术本身不能确保业务规则的100% 测试覆盖率。 状态转换测试是一种黑盒测试技术,它可以用来设计一个需要有限数量状态的系统的测试用例,并且在特定事件发生时可以从一个状态转换到另一个状态。...这是一种基于技能的技术,没有任何规则。错误猜测更多的是关于经验,虽然经验是必需的,但它不能证明是一切 用例测试在这个技术中,用例/场景被用来编写测试用例。用例中描述了用户和系统之间的交互。

    86910

    代码重构(三):数据重构规则

    当然该重构规则不是必须执行的,因为如果你直接使用self来访问类的属性如果不妨碍你做扩展或者维护,那么也是可以的,毕竟直接访问变量更为容易阅读。...(3).创建完Order与Customer类后,紧接着我们要创建测试用例了。并通过测试用例来发现问题,并在重构时对该问题进行解决。在测试用例中我们创建了三个订单,为每个订单关联一个Customer。...下方代码中的Lender类与上面的Lender类中的lendBooks不同,我们使用了另一个集合类型,也就是字典,而字典的key就是书名,字典的值就是书的对象。...就是当你的各个子类中唯一的差别只在“返回常量数据”的函数上。当遇到这种情况时,你就可以将这个返回的数据放到父类中,并在父类中创建相应的工厂方法,然后将子类删除即可。...下方代码中,将PersonType声明了一个类,在类中添加了两个字段,一个是isMale,另一个是code,这两个字段恰好是上述两个子类函数中返回的不同值。

    1K10

    代码重构(三):数据重构规则

    当然该重构规则不是必须执行的,因为如果你直接使用self来访问类的属性如果不妨碍你做扩展或者维护,那么也是可以的,毕竟直接访问变量更为容易阅读。...(3).创建完Order与Customer类后,紧接着我们要创建测试用例了。并通过测试用例来发现问题,并在重构时对该问题进行解决。在测试用例中我们创建了三个订单,为每个订单关联一个Customer。...从测试用例中可以看出,关联的消费者数据为同一个人,但是这一个人在内存中占用了不同的存储空间,如果一个订单中的用户信息进行了更改,那么其他订单中的用户信息是不会更新的。...就是当你的各个子类中唯一的差别只在“返回常量数据”的函数上。当遇到这种情况时,你就可以将这个返回的数据放到父类中,并在父类中创建相应的工厂方法,然后将子类删除即可。...下方代码中,将PersonType声明了一个类,在类中添加了两个字段,一个是isMale,另一个是code,这两个字段恰好是上述两个子类函数中返回的不同值。

    1.2K60

    前端领域的 “干净架构”

    我同意上面这个观点,但我认为系统架构的另一个主要目标是系统的可扩展性。我们应用的需求是不断变化的。我们希望我们的程序可以非常易于更新和修改以满足持续变化的新需求。...如果一切都符合我们预期的,我们就可以开始设计领域转换了。 创建数据转换 我们刚刚设计的这些类型数据会发生各种各样的事情。我们可以添加商品到购物车、清空购物车、更新商品和用户名等。...如何实现现在不是重点,我们可以在最后再考虑调用哪些外部服务,这样代码才能尽量保证低耦合。 另外还要注意,我们按功能拆分接口。与支付相关的一切都在同一个模块中,与存储相关的都在另一个模块中。...在不同的实体和可扩展之间选择,推荐使用类似于 BEM 中的块和修饰符概念来帮助你思考,如果我在 BEM 的上下文中考虑它,它可以帮助我确定我是否有一个单独的实体或代码的“修饰符扩展”。...相互依赖的用例 第二个问题是用例相关的,通过一个用例的事件触发另一个用例。 我知道并且对我有帮助的处理这个问题的唯一方法是将用例分解为更小的原子用例。它们将更容易组合在一起。

    1.3K20

    uml用例图详解_uml模型图

    但对于每一个用例,还需要详细地描述信息,以便让别人对于整个系统由更加详细的了解,这些信息包含在**用例规约(Use Case Specification)**中。...一个基础用例可以拥有一个或者多个扩展用例,这些扩展用例可以一起使用。需要注意的时:在扩展关系中是基础用例而不是扩展用例被当做例子使用。...扩展关系与包含关系的不同点如下: 在扩展关系中,基础用例提供了一个或者多个插入点,扩展用例为这些插入点提供了需要插入的行为。而在包含关系中,插入点只能有一个。...此外,子用例还可以添加、覆盖、改变继承的行为。 在UML中,用例的泛化关系是通过一个三角箭头从子用例指向父用例来表示的。...而用例的包含关系中,基础用例在目的上可以完全不同,但是它们都有一段相似的行为,它们的相似是部分的相似不是整体的相似。

    3K30

    iOS 面试策略之系统框架-设计模式

    功能是完成了,然而效率上不是很高,代码逻辑在日后也可能需要返工重构。 [1240] 我个人认为,突破这个瓶颈的捷径就是掌握设计模式。...关键词:#创建型 #结构型 #行为型 iOS 开发中的设计模式有很多,一般最常见的有这 7 种: MVC:是应用的一种基本架构,主要目的是将不同的代码归于不同的模块,做到低耦合、代码分配合理、易于扩展维护的目的...适配器模式(Adapter):将一个类的接口转化为另一个类的接口,使得原本互不兼容的类可以通过接口一起工作。 外观模式(Façade):用一个公共接口来连接多个类或其他数据类型。...它更强大的地方在于可以为 Protocol 扩展完成默认实现。 Delegation 是程序中一个对象代表另一个对象,或者一个对象与另外一个对象协同工作的模式。...;如何获取,具体内容请转看-我的GitHub 我的:GitHub地址

    1.6K20

    【数据架构】Netflix 万亿级实时数据基础架构的四个创新阶段

    我希望这篇文章能帮助平台工程师开发他们的云原生、自助式流数据平台,并在许多业务功能中扩展用例(不一定来自我们的成功,也许更多来自我们的失败)。...挑战 挑战 1:自定义用例需要不同的开发人员和运营经验。...我们逐渐扩大了运营投资,例如自动扩展、托管部署、智能警报、回填解决方案等。 学习 学习 1:支持新的自定义用例的新产品入口点是必要的演进步骤。这也是一个重新架构/重构并融入现有产品生态系统的机会。...机会 我将在这部分相对简短,并在以后的博客文章中扩展细节。 使用流连接世界。对于流处理而言,除了低延迟处理的优势外,它在现代数据平台中越来越显示出更为关键的优势:连接各种技术并实现流畅的数据交换。...这篇博文描述了在 Netflix 构建流处理基础设施的高级迭代之旅。我很想听听您对有趣之处的反馈,以便我可以跟进未来的博客文章。 根据设计,我在这篇文章中省略了许多技术细节。

    64230

    来一场Java高级的面试,看看自己啥水准

    这是在 Java 中不支持运算符重载的另一个好处。省略运算符重载使语言更容易处理,这反过来又更容易开发处理语言的工具,例如 IDE 或重构工具。Java 中的重构工具远胜于 C++。 4....同时,String 是 final 的,因此没有人可以通过扩展和覆盖行为来破坏 String 类的不变性、缓存、散列值的计算等。String 类不可变的另一个原因可能是由于 HashMap。...因此,在Java中,用字符数组用存储密码比字符串是更好的选择。虽然仅使用char[]还不够,还你需要擦除内容才能更安全。 6. 如何使用双重检查锁定在 Java 中创建线程安全的单例?...这不是一个延迟加载单例: 单例模式用静态工厂方法 这是我最喜欢的在 Java 中影响 Singleton 模式的方法之一,因为 Singleton 实例是静态的,并且最后一个变量在类首次加载到内存时初始化...不指定 serialVersionUID的后果是,当你添加或修改类中的任何字段时, 则已序列化类将无法恢复, 因为为新类和旧序列化对象生成的 serialVersionUID 将有所不同。

    1K10

    策略引擎对决——OPA与OpenFGA与Cedar

    在这个小组讨论中,我们将深入探讨如何为您的用例选择最佳决策引擎,以及如何一起运行多个引擎以及有效地扩展它们。”...软件中的所有东西都有权衡——有些解决方案在一个用例中表现出色,但在另一个用例中可能并不适用。我们在这里探讨这些差异,并为您提供做出最佳决策的工具。”...但是,具体的关联关系,例如谁是所有者,则存在于数据中。” 他解释了这种组合如何实现灵活性和可扩展性: “这是一个混合模型。策略定义规则,而数据中的关系则实例化这些规则。...集中式与分散式 在选择不同的策略引擎时,集中式和分散式策略引擎部署之间的争论是另一个关键方面。每种方法在性能、一致性和复杂性方面都有权衡,所有这些都与具体的用例有着不同的契合度。...我无法自信地说权限是否在所有服务中都得到一致的评估。” 她强调了集中化如何带来清晰度和一致性: “我们选择了一个集中式系统,以便每个服务都可以提出相同的权限问题,并始终获得相同的答案。

    11910

    一种Python全局配置规范以及其修改

    这是在Python中自定义数据类型的基本操作了,自定义完成后然后写一个装饰器将继承的类转化成单例的类。 单例模式的写法可以看Stackoverflow上关于单例模式的高票回答。...但这个写法有个问题,装饰后的返回的不是一个类,而是一个函数,虽然Python语法讲究一切皆对象,但函数是享受不到类的诸如继承之类的特性的。...单例字典是我在项目初期引入,并在项目的迭代过程中给我造成最大困扰的一个东西,在开始时几乎将所有的配置都写入到这个字典中,然后在程序运行中这个字典又被分散在程序各处的各个实例修改,运行到后面根本不知道字典里有什么...不过由于GIL,倒是不需要考虑锁的问题,可能是唯一的一个幸事。 在后期将这个庞大的字典进行重构,重构的过程按照下面的方式进行: 1、将各个类中该字典的引用点,由各个方法收拢到init方法。...3、将子函数中直接引用单例字典的参数放到函数的参数列表中,由调用方获取单例字典内容,由传参的方法传入被调用函数,这样做是为了满足函数式编程中纯函数的原则。 不应该这么用: ? 应该这样用 ?

    2K90

    TDD(测试驱动开发)之一二事

    原理 测试驱动开发的基本思想就是在开发功能代码之前,先编写测试代码。也就是说在明确要开发某个功能后,首先思考如何对这个功能进行测试,并完成测试代码的编写,然后编写相关的代码满足这些测试用例。...可以记录成一个 TODO 列表。 2) 快速完成针对此功能的测试用例编写。 3) 测试代码编译不通过。 4) 编写对应的功能代码。 5) 测试通过。 6) 对代码进行重构,并保证测试通过。...一顶帽子: 开发人员开发过程中要做不同的工作,比如:编写测试代码、开发功能代码、对代码重构等。做不同的事,承担不同的角色。...应该在任何阶段想添加功能需求问题时,把相关功能点加到测试列表中,然后继续手头工作。然后不断的完成对应的测试用例、功能代码、重构。一是避免疏漏,也避免干扰当前进行的工作。 测试驱动: 这个比较核心。...完成某个功能,某个类,首先编写测试代码,考虑其如何使用、如何测试。然后在对其进行设计、编码。 先写断言: 测试代码编写时,应该首先编写对功能代码的判断用的断言语句,然后编写相应的辅助语句。

    75860

    10个最难回答的Java面试题

    这是在 Java 中不支持运算符重载的另一个好处。省略运算符重载后使语言更容易处理,如静态分析等,这反过来又更容易开发处理语言的工具,例如 IDE 或重构工具。Java 中的重构工具远胜于 C++。...同时,String 是 final 的,因此没有人可以通过扩展和覆盖行为来破坏 String 类的不变性、缓存、散列值的计算等。String 类不可变的另一个原因可能是由于 HashMap。...因此,在Java中,用字符数组用存储密码比字符串是更好的选择。虽然仅使用char[]还不够,还你需要擦除内容才能更安全。 6. 如何使用双重检查锁定在 Java 中创建线程安全的单例?...这不是一个延迟加载单例: 单例模式用静态工厂方法 这是我最喜欢的在 Java 中影响 Singleton 模式的方法之一,因为 Singleton 实例是静态的,并且最后一个变量在类首次加载到内存时初始化...不指定 serialVersionUID的后果是,当你添加或修改类中的任何字段时, 则已序列化类将无法恢复, 因为为新类和旧序列化对象生成的 serialVersionUID 将有所不同。

    81920

    .NET重构—单元测试的代码重构

    ,重构能有今天的风光影响力完全少不了单元测试的功劳;最近一段时间写单元测试用例的时间远超过我写逻辑代码的时间和多的多的代码量,这是为什么?...,就当抛砖引玉吧; 2.1.1】公用的Mock对象 首要的任务就是将公共的Mock接口提取出来,因为这一类接口是肯定会在各个用例中共享的,提取过程过主要分为两个重构过程; 第一:将用例中的公用接口放到类的声明中...这样可以解决内部重复问题,但是这里需要小心的地方是,当我们在不同的用例之间共享部分Mock逻辑的时候可能会出现问题;比如我们在OrderService_GetOrders_NormalFlows用例中,...提取出来的抽象基类能在后面的单元测试重构中帮很大忙,也是为了后面的面向特定领域的单元测试框架做要基础工作;由于不同的单元测试类具有不同的基类,这里需要我们自己的分析抽象,比如这里跟Service相关的...,会有几十个字段都需要进行测试验证,再加上N多个用例,会使相同的代码变的很多; 那么我们同样需要将这部分的代码提取出来放到基类中去,适当的留有空间让用例中修改的特殊的字段; 完整的实体构造: 1 Order

    1.3K60

    对 React 组件进行单元测试

    而单元测试作为一种“提纲挈领、保驾护航”的基础手段,为开发提供了“围墙和脚手架”,可以有效的改善这些问题。...而当我们反过头来,对既有代码补充测试用例,使其测试覆盖率不断提高,并在此过程中改善原有设计,修复潜在问题,同时又保证原有接口不收影响,这种 TDD 行为虽然没人称之为“测试驱动重构”(test driven...React 单元测试常见案例 用例的预处理或后处理 可以用beforeEach和afterEach做一些统一的预置和善后工作,在每个用例的之前和之后都会自动调用: describe('test components...; }); ... }); 调用组件的“私有”方法 对于一些组件中,如果希望在测试阶段调用到其一些内部方法,又不想对原组件改动过大的,可以用instance()取得组件类实例...扩展阅读: 一个重构的实例 https://mp.weixin.qq.com/s?

    4.3K40
    领券