定义一系列算法,将每一个算法封装起来,并使它们可互换。策略允许算法独立于使用它的客户端。
GOF设计模式中的行为模式家族处理应用中对象的职责和他们在运行时如何通信。这些行为模式在之前的已经写过了,他们是命令模式、责任链模式、迭代器模式、中介者模式、解释器模式、观察者模式、备忘录模式和状态模式。在这个章节将要讨论策略模式,最基础的设计模式之一,所有的开发者在他们的开发包中应该具备。正如上面提到的,策略模式的含义是,当你有多个算法并且你想作为独立的对象对待它们,这些对象可以在运行时动态的互换来达到应用程序的高内聚和松耦合时,建议你使用策略模式。
简介在企业应用程序中,通常会有使用多个算法实现某些业务需求的对象。一个常见的例子是支持多种排序算法的数字排序类,如冒泡排序、归并排序和快速排序。同样的,一个文件压缩类可以支持不同的压缩算法,如ZIP,GZIP,lz4,甚至一个自定义的压缩算法。另一个例子是一个数据加密类,对数据进行加密,使用不同的加密算法,如AES,TripleDES和密码学。通常情况下,程序员往往把所有的算法逻辑写在宿主类,导致在一个类中有多个开关或条件判断语句。下面的示例展示了一个这样的类的结构,该类支持多个算法对数据进行加密。
上面的加密类有不同的加密算法的条件语句。在运行时,代码依次通过语句判断执行客户端指定算法进行加密。这是一个紧耦合和死板的软件,是很难改变。你能想象到的后果,如果你想实现一个新的加密算法,比如说TripleDES或自定义的加密算法。你会打开并修改加密类。同样,如果一个现有的算法需要改变,加密类将再次需要修改。你可以看到,我们的加密类是明显违反了开闭原则–面向对象的设计原则。按照原则,新的功能应该通过编写新的代码来增加,而不是修改现有代码。发生违反原则的情况是因为我们没有遵循面向对象(OO)编程实践的基本原则,即“封装变化”。
企业应用程序中的这些缺陷会导致整个应用程序的涟漪效应,使应用程序变得脆弱,并且可以通过使用策略模式避免它们。使用策略模式,我们定义了一组相关的算法,将它们封装在与主类(Encryptor)分开的类中。客户端可以选择在运行时使用的算法。通过这样做,我们可以轻松地添加一个新的算法或删除而不用修改其他现有的算法或主机类。每个算法类坚持单一责任原则,另一个面向对象的原则,他们只关注一个特定的算法对数据进行加密,这是目前在我们Encryptor类中所缺乏的。此外,较小的算法类,单元测试变得更容易专注于测试一个特定的情况。
参与者使用我们的数据加密的例子,我们将首先实现接口,接口将用于所有不同的加密算法特定的类。让我们命名接口为EncryptionStrategy,命名算法的具体类AesEncryptionStrategy和BlowfishEncryptionStrategy。最终,这些是我们的策略。
接下来我们将重构加密类,删除所有条件语句和委托任何加密算法的客户指定的具体要求。
现在我们可以将策略模式的参与者归纳为:
Strategy 策略类(encryptionstrategy):支持所有特定算法的接口类。
ConcreteStrategy 具体策略类(AesEncryptionStrategy和blowfishencryptionstrategy):实现算法使用策略接口。
Context 上下文(Encryptor)为客户端加密数据提供接口。上下文维护一个对Strategy对象的引用、通过客户端使用ConcreteStrategy实例化和初始化一个对象。
应用策略模式让我们使用策略模式来实现上面Encryptor类实现的同样的需求。我们从Strategy接口开始,然后转移到ConcreteStrategy类
下面我们写Context (上下文)Encryptor类:
测试类: