设计模式(一):“穿越火线”中的“策略模式”(Strategy Pattern)

简介:

在前段时间呢陆陆续续的更新了一系列关于重构的文章。在重构我们既有的代码时,往往会用到设计模式。在之前重构系列的博客中,我们在重构时用到了“工厂模式”、“策略模式”、“状态模式”等。当然在重构时,有的地方没有点明使用的是那种设计模式。从今天开始,我们就围绕着设计模式这个主题来讨论一下我们常用的设计模式,当然“GoF”的23种设计模式不会全部涉及到,会介绍一些常见的设计模式。在接下来我们要分享的设计模式这个系列博客中,还是以Swift语言为主来实现每种设计模式的Demo。并且仍然会在GitHub上进行Demo的分享,希望与大家相互交流,相互学习,有不足之处还望批评指正。

今天博客的主要思路是先围绕着“穿越火线”中的角色与武器的关系,通过策略模式来设计实现这种关系,整体的来整体感受一下“策略模式”的优点。然后再参考《Head First Design Patterns》这本书中的鸭子的示例,来一步步使用Swift来实现策略模式的案例。当然我们只是参考《Head First Design Patterns》中的示例,本篇博客中的示例与其中的示例还是有所区别的。大部分设计模式的案例都是使用Java实现的,我们依然会使用Swift来实现。还是那句话,设计模式是针对面向对象编程语言的,而不是针对某一种编程语言,Swift是面向对象的语言,所以设计模式用于Swift编程中是没有问题的。废话少说,进入今天博客的主题。

 

一、穿越火线中的“策略模式”(Strategy Pattern)

当然,这个示例是我YY出来的示例,不是“穿越火线”这个游戏的设计方案呢。说到"穿越火线"如果你没有玩过,那应该听过吧,就是“CrossFire”。我平时不怎么玩游戏,穿越火线之前体验过,不过只有被爆头的份儿。听说那些游戏玩家现在不怎么玩儿“CF”啦,改玩儿Dota,LOL啦,真的是这样吗?我个人对于游戏而言是外行了,不过玩个超级玛丽、魂斗罗、植物大战僵尸、节奏大师还是可以的(坏笑)。

言归正传,今天我们就模拟穿越火线中角色和武器的关系,使用“策略模式”来实现。首先我们先分析一下这个场景,穿越火线中角色分为不同的等级,也就是“军衔”了,简单的说几个吧,由高到底对应着“军师旅团营连排小工兵”,上面的是组织,军衔莫过于各种级的士官,少中上尉,少中上校,少中上将(应该对吧,本人不太专业呢,不过用于咱们要实现的例子是够了)。我虽然不怎么会打CF,可是我会玩军棋呢。

我是不是刷知乎刷多了,不能在这儿“一本正经的胡说八道”了。言归正传,不同的角色所配备的武器装备也不同,等级越高所使用的武器装备也就越厉害。我们如何使用面向对象来表达这种角色与武器之间的关系呢?我们先看一下下方的类“类图”。

      

上面是一个简化的类“类图”,上面这种形式可以表达我们之前的那种场景。“军人”是一个父类,其他具体等级的军官都继承自“SuperClass”。那么问题来了,在上面那种模式下,如果只有“少尉”和“中尉”配备某种武器,其他军官不配备,我们就要在“少尉”和中尉的类中分别添加要实现的武器,那么这样会产生冗余的代码。还有个问题是上面的设计形式不利于扩展,比如“少尉”也要配备狙击步枪,岂不是得从“中尉”中的狙击步枪的方法复制到“少尉”中。这样也会产生重复代码的。那么我们该怎样去解决这个问题呢?

有童鞋说了,在Swift中的Protocol(协议,也就是Java中的接口)可以提供默认的实现。也就是声明一个protocol,然后通过extension来为协议添加默认实现,只要是类遵循该协议,那么这个类就拥有了这个默认实现(当然,Java中的接口是不能通过后期的延展来为其添加默认实现的)。如果在Swift中使用接口的默认实现的话,如果要对上述军官扩充装备的话,设计中的类“类图”(不是类图,但与类图相似)实现如下所示:

       

上面这种设计模式虽然不会产生重复的代码,但是如果给“军官”添加的武器过多的话,那么会导致相应的类中实现的接口过多,这并不是我们想要的。下方将会给出一个良好的解决方案,也就是使用策略模式。

 

二、使用“策略模式”(Strategy Pattern)对上述关系进行设计

“策略模式”的定义大概是:策略模式,将不同的策略(算法)进行封装,让他们之间可以相互的替换,此模式让策略的变化独立于使用策略的用户。在设计模式中有不同的设计原则,其中有一条就是“找出程序中可能需要变化的地方,并且把它吗独立出来,不要和不变的代码混在一起”。根据这条设计原则,然后结合着上述示例不难分析出来,在上述示例中,使用军官使用的不同武器是可以变化的,使用不同的武器正是采取不同的策略呢。

所以经过上述讨论,我们可以使用“策略模式”来重新设计上面的结构。简单的说就是把变化的“武器”部分进行提取,然后在军官中进行使用,不同的军官可以采取不同的策略,并且可以随时替换。下面是我们使用“策略模式”重新设计后的关系,具体请看下图。

   

在上面的类“类图”中我们对可变的“武器策略进行了提取”。我们使用了WeaponBehavior协议来规定武器的策略,使得不同的武器对外有统一的接口,在此就是使用武器,也就是开火。不同的武器使用不同的的“开火策略”,但是对外的接口都是一样的。设计原则中有一条是“面向接口编程,而不是面向实现编程”。这里所指的接口可以是协议,可以是抽象类,也可以是超类,其实就是利用面向对象的“多态”特性。上面的红框中实现的就是所有不同的策略。

而绿框中是我们的用户,也就是军官的定义,是我们不变的部分。在军官中也有一个基类,在基类中定义了军官的共性,其中依赖于“武器策略”的接口。在军官超类中使用“武器策略”的协议声明了一个对象,该对象就是该军官所采取的武器策略。在军官的超类中可以通过setWeapon()方法采取不同的策略,其中fire()方法就是使用该“武器策略”进行开火。在具体的军官中的changeXXX()方法就是调用setWeapon()方法进行策略切换的方法。具体内容请看下方的具体实现。

 

三、上述“策略模式”(Strategy Pattern)的具体实现

上面给出了“武器策略模式”的个个部分之间的关系,并给出了相应的解释。如果对此你感觉到抽象的话,那么我们接下来就用相应的Swift代码去实现上述示例。也就是将上面的理论部分进行具体实现,当然在此我们用的是Swift语言,但是,你完全可以使用其他的面向对象编程语言。下面就是我们具体的代码实现。

下方就是我们对“武器策略”的实现,红框中对应的就是上面图中的WeaponBehavior(协议)接口,下方绿框中就是不同武器的策略,每个武器策略都遵循了WeaponBehavior协议。并且实现了相应的useWeapon()方法。

    

对“武器策略”模块实现完毕后,接下来我们就得实现军官模块了。也是根据上面我们所画的“模式结构图”来实现我们的“军官模块”,下方Character就是所有军官的基类,其中默认的武器策略weapon就是手枪(PistolBehavior),其中有设置策略和改变策略的方法,并且还有使用策略的方法(fire())。下方的红框就是实现的不同的军官了,不同的军官可以有不同的切换策略的方法。具体如下所示:

   

上面就是我们全部实现的代码,下方是我们的测试用例和输出结果。下方我们创建了一个“中尉”军官----lieutenant,军官默认的是开的手枪。但是可以调用相应的changeXXX()方法来切换武器策略。开手枪时,发现火力不行,然后就调用changeHK()方法切换到HK48步枪。这种关系使用“策略模式”就比较灵活,并且便于扩展。比如中尉现在也要配备大狙,因为现在已经有大狙这个武器策略了,所以我们现在只需在中尉中添加相应的change方法,传入大狙的武器策略即可,具体的就不在演示了。

   

相关文章
|
7天前
|
设计模式 算法 测试技术
PHP中的设计模式:策略模式的应用与实践
在软件开发的浩瀚海洋中,设计模式如同灯塔,指引着开发者们避开重复造轮子的暗礁,驶向高效、可维护的代码彼岸。今天,我们将聚焦于PHP领域中的一种重要设计模式——策略模式,探讨其原理、应用及最佳实践,揭示如何通过策略模式赋予PHP应用灵活多变的业务逻辑处理能力,让代码之美在策略的变换中熠熠生辉。
|
8天前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深入探索与实践在软件开发的广袤天地中,PHP以其独特的魅力和强大的功能,成为无数开发者手中的得力工具。而在这条充满挑战与机遇的征途上,设计模式犹如一盏明灯,指引着我们穿越代码的迷雾,编写出更加高效、灵活且易于维护的程序。今天,就让我们聚焦于设计模式中的璀璨明珠——策略模式,深入探讨其在PHP中的实现方法及其实际应用价值。
策略模式,这一设计模式的核心在于它为软件设计带来了一种全新的视角和方法。它允许我们在运行时根据不同情况选择最适合的解决方案,从而极大地提高了程序的灵活性和可扩展性。在PHP这门广泛应用的编程语言中,策略模式同样大放异彩,为开发者们提供了丰富的创作空间。本文将从策略模式的基本概念入手,逐步深入到PHP中的实现细节,并通过一个具体的实例来展示其在实际项目中的应用效果。我们还将探讨策略模式的优势以及在实际应用中可能遇到的挑战和解决方案,为PHP开发者提供一份宝贵的参考。
|
9天前
|
设计模式
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
这篇文章详细解释了工厂模式,包括简单工厂、工厂方法和抽象工厂三种类型。每种模式都通过代码示例展示了其应用场景和实现方法,并比较了它们之间的差异。简单工厂模式通过一个工厂类来创建各种产品;工厂方法模式通过定义一个创建对象的接口,由子类决定实例化哪个类;抽象工厂模式提供一个创建相关或依赖对象家族的接口,而不需要明确指定具体类。
设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)
|
9天前
|
设计模式 运维 算法
Java设计模式-策略模式(15)
Java设计模式-策略模式(15)
|
17天前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深度解析
在PHP开发中,策略模式是一种行为设计模式,它允许你在运行时根据不同情况选择不同的算法或行为。本文将深入探讨策略模式的定义、结构、使用场景以及在PHP中的实现方法,并通过实例展示如何在PHP项目中应用策略模式来提高代码的灵活性和可维护性。
|
18天前
|
设计模式 人工智能 算法
PHP中的设计模式:策略模式的深入解析与实践软件测试中的人工智能革命:提升效率与准确性的新篇章
在PHP开发中,理解并运用设计模式是提升代码质量和可维护性的重要途径。本文聚焦于策略模式(Strategy Pattern),一种行为型设计模式,它允许在运行时选择算法或业务规则。通过本文,我们将深入探讨策略模式的定义、结构、使用场景以及如何在PHP项目中有效地实现和利用策略模式。不同于性能优化等技术性摘要,本文着重于提供对策略模式全面而实用的理解,助力开发者编写出更加灵活和可扩展的应用程序。 本文深入探讨了人工智能在软件测试领域的应用,揭示了其如何显著提高测试过程的效率和准确性。通过实际案例分析,展示了AI技术在自动化测试、缺陷检测及结果分析中的关键作用,并讨论了实施AI测试策略时面临的挑
17 3
|
9天前
|
设计模式 Java
设计模式--适配器模式 Adapter Pattern
这篇文章介绍了适配器模式,包括其基本介绍、工作原理以及类适配器模式、对象适配器模式和接口适配器模式三种实现方式。
|
9天前
|
设计模式 存储 算法
PHP中的设计模式:策略模式的深入解析与应用在软件开发的浩瀚海洋中,PHP以其独特的魅力和强大的功能吸引了无数开发者。作为一门历史悠久且广泛应用的编程语言,PHP不仅拥有丰富的内置函数和扩展库,还支持面向对象编程(OOP),为开发者提供了灵活而强大的工具集。在PHP的众多特性中,设计模式的应用尤为引人注目,它们如同精雕细琢的宝石,镶嵌在代码的肌理之中,让程序更加优雅、高效且易于维护。今天,我们就来深入探讨PHP中使用频率颇高的一种设计模式——策略模式。
本文旨在深入探讨PHP中的策略模式,从定义到实现,再到应用场景,全面剖析其在PHP编程中的应用价值。策略模式作为一种行为型设计模式,允许在运行时根据不同情况选择不同的算法或行为,极大地提高了代码的灵活性和可维护性。通过实例分析,本文将展示如何在PHP项目中有效利用策略模式来解决实际问题,并提升代码质量。
|
7天前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提升代码的可维护性与扩展性在软件开发过程中,设计模式是开发者们经常用到的工具之一。它们提供了经过验证的解决方案,可以帮助我们解决常见的软件设计问题。本文将介绍PHP中常用的设计模式,以及如何利用这些模式来提高代码的可维护性和扩展性。我们将从基础的设计模式入手,逐步深入到更复杂的应用场景。通过实际案例分析,读者可以更好地理解如何在PHP开发中应用这些设计模式,从而写出更加高效、灵活和易于维护的代码。
本文探讨了PHP中常用的设计模式及其在实际项目中的应用。内容涵盖设计模式的基本概念、分类和具体使用场景,重点介绍了单例模式、工厂模式和观察者模式等常见模式。通过具体的代码示例,展示了如何在PHP项目中有效利用设计模式来提升代码的可维护性和扩展性。文章还讨论了设计模式的选择原则和注意事项,帮助开发者在不同情境下做出最佳决策。
|
21天前
|
设计模式 算法 安全
设计模式——模板模式
模板方法模式、钩子方法、Spring源码AbstractApplicationContext类用到的模板方法
设计模式——模板模式