设计模式——策略模式之我见

策略模式
小疑惑

上篇文章说了简单工厂的模式,简单工厂的模式是最基本的设计模式,它主要用来生产对象的。试想一下,如果对一个场景来说,经常会有使用不同算法的需求(比如商场促销时,今天打九折,明天打八折,后天又开始满减,再往后又开始返积分。。。),如果利用简单工厂模式的话,需要实现多个继承自父类的子类,如果有一百种变化,使用简单工厂模式的话,岂不是要写一百个子类,那样的话,也太过复杂了。而且,如果每次改变工厂类的实现,那岂不是每次都要重新编译一次。如果遇到这种算法经常改变的问题,就一个该使用策略模式了。(其实可以看到,这种情况下,变化的是具体的算法,而不是单纯的一个对象那么简单了。)

定义

Strategy ||Policy design pattern;它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。

理解

比如针对商场促销,商场如何促销,打折还是满减还是返利,都是一些算法,用工厂类来生成算法对象没有错误,但是算法本身是一种策略,最重要的是算法随时都可以相互替换。可以相互 替换是重点。那么 封装的时候,就需要思考如何实现相互替换了。

策略模式实现时,也需要定义一个算法的抽象类|接口,然后让具体的算法去实现它。策略模式和简单工厂模式的区别在于需要定义一个上下文的类context,并且要在上下文类中定义一个算法的抽象类变量,并且添加一个以算法类父类为 参数的构造函数,然后再添加一个执行算法的方法,并且再这个方法中调用算法类的抽象方法。当客户端实例化上下文对象时,利用对象的多态性,传入具体的算法,初始化上下文类中的算法类,然后调用上下文类的执行算法的方法(这时实际调用的是你传入上下文中的算法类所重写的父类算法方法。

对比工厂模式

自己简单的总结了下这两个模式的区别,如下表

比较 简单工厂模式 策略模式
目的 生产对象,返回指定对象 执行算法,返回算法结果
客户端调用的类 工厂类,通常是***Factory 上下文类,通常是***Context
客户端调用的方法 create*** execute***
抽象父类 需要 需要
判断逻辑的位置 工厂类 客户端
具体方法执行位置 在客户端调用工厂类产生具体类后,用户在客户端调用 具体算法的执行过程,放在了上下文类的一个execute方法中,实现了具体算法和用户的隔离
思考

如果使用了策略模式,具体使用什么算法的判断逻辑又会被写在了客户端,这样又增加了客户端的代码,这样是不太合理的。我们知道,简单工厂模式通过过工厂类,将判断使用什么类的判断逻辑放在了服务端,那么如果简单工厂和策略模式结合下,不就可以解决在客户端进行逻辑判断的问题了。

简单工厂模式和策略模式结合

在策略模式的基础上,增加一个新的变量,定义为决定算法变量,然后新建一个以这个变量为参数的构造方法,并且在这个构造方法中,写入一些判断逻辑,决定使用什么具体的算法来实例化上下文类中的算法父类,其他的地方保持不变。这样,当客户端调用上下文类来实例化算法时,通过传入不同的决定算法变量,然后执行上下文的execute方法,就可以得到希望的结果了。

总结

策略模式是一种定义一系列算法的方法,所有这些算法完成的都是相同的工作,只是实现不同,他可以以相同的方式调用所有的算法,减少了各类算法类与使用类之间的耦合。

策略模式的strategy类抽象父类,为context上下文类定义了一系列的可供重用的算法或行为。这其中主要利用了Java的继承特性,也是用到了里氏替换的设计模式。

策略模式跟简单工厂的结合,更是将客户端和服务端分离开来,降低了客户端的调用难度,并且,简化了单元测试。

在这其中可以看到,当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择合适的行为。通过将这些行为封装在一个个独立的strategy类中,可以在使用这些行为的类中消除条件语句。所以,策略模式就是用来封装算法的。但在实际中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同的时间应用不同的业务规则时,就可以考虑使用策略模式。


后记

这周没事的时候,就来这写写文章,感觉还不错。而且终于理解到好记性不如烂笔头,必须把自己看得想的记下来比较好,这样往后的时候还能看看自己写的东西想起点什么。这不,趁着周六赶紧又写两篇文章,要不然又要感觉自己白白消费了一天。努力吧,自己的亲人还有爱人可都期盼着呢。
用高中数学老师的话激励激励吧 :

人勤事事易,人懒事事难。成王败寇,适者生存。

———SAID BY MR JATHAM ZHANG

猜你喜欢

转载自blog.csdn.net/Jatham/article/details/81809947