码迷,mamicode.com
首页 > 编程语言 > 详细

策略模式(java)

时间:2018-02-07 00:40:17      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:名称   代码结构   ati   class   上下文   设计   image   body   解决   

  GOF 《设计模式:可复用面向对象软件设计的基础》中的模式,应当算是模式归纳的鼻祖(并非他们最早发现/使用了模式,而是将已有的模式进行了整合归纳),而我们现在对于模式的学习基本上都是基于Gof的设计模式。今天主要说说行为型模式中的一个:策略模式。

模式定义

  意图:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

 

  动机:

  •   客户程序如果直接包含策略算法代码,将会变得很复杂。(策略算法本身足够复杂)
  •   不同的时候需要不同的算法   (if....else....)

模式类图

技术分享图片

阐述与讨论

  策略模式是我们在开发中常用的模式之一。网上关于策略模式也有很多介绍,这里再次提出,是期望给出“正规”的模式,在我初学设计模式时,也经常会被搞得不知所云,众说纷纭还给出代码,但几乎都不太一样,我也曾被策略模式搞得迷糊(主要是context),因此再次找出GOF原本进行分析- -

  最常见的疑惑问题:策略模式和简单工厂模式进行比较。两者区别还是比较大的,不管是从语义还是实现上。

  下面给出简单工厂的类图(GOF模式中没有简单工厂---只有抽象工厂和工厂方法):

  技术分享图片

  对比简单工厂和策略模式类图很容易发现区别: 工厂(Factory)是依赖Product接口,同时依赖于具体产品(ProductA和ProductB),而策略模式中,Context是包含了Stategy接口,同时并不依赖具体的策略类。

通过代码很容易就可以看出区别:

  策略模式代码:

 1
 1 package strategydemo;
 2 /**
 3  * @author : xiaolu 2018年2月6日
 4  * @todo   : 策略上下文
 5  */
 6 public class Context {
 7     // 包含关系
 8     private Strategy strategy ; 
 9     // 这个类中包含具体策略需要的其他参数,必要时可以将自己传递给策略类(GOF)
10     public Context(Strategy strategy){
11         this.strategy = strategy;
12     }
13     
14     public int get(){
15         return this.strategy.algorithm();
16     }
17 }

 

 1 package strategydemo;
 2 
 3 /**
 4  * @author : xiaolu 2018年2月6日
 5  * @todo   : 策略接口
 6  */
 7 public class StrategyB implements Strategy {
 8     @Override
 9     public int algorithm() {
10         // 这里的逻辑应当比较复杂,否则没有必要使用策略类
11         // 仅作说明
12         return 0;
13     }
14 
15 }
 1 package strategydemo;
 2 
 3 public class StrategyA implements Strategy {
 4     @Override
 5     public int algorithm() {
 6         // 这里的逻辑应当比较复杂,否则没有必要使用策略类
 7         // 仅作说明
 8         return 1;
 9     }
10 
11 }
 1 package strategydemo;
 2 
 3 /**
 4  * @author : xiaolu 2018年2月6日
 5  * @todo   : 策略接口
 6  */
 7 public class StrategyB implements Strategy {
 8     @Override
 9     public int algorithm() {
10         // 这里的逻辑应当比较复杂,否则没有必要使用策略类
11         // 仅作说明
12         return 0;
13     }
14 
15 }
 1 package strategydemo;
 2 /**
 3  * @author : xiaolu 2018年2月6日
 4  * @todo   : 客户端
 5  */
 6 public class Main {
 7     public static void main(String[] args) {
 8         // 具体策略类
 9         Strategy a = new StrategyA();
10         //Context
11         Context ctx = new Context(a);
12         
13         System.out.println(ctx.get());
14     }
15 }

代码结构和名称大体按照策略类图所给出的。可以看到客户端是“知道”(或者说依赖于)具体策略类的。而Context对于具体策略类并不存在任何依赖(无知),只是“包含”(类中属性)了策略接口。

下面给出简单工厂实现:

1 package simplefactory;
2 
3 /**
4  * @author : xiaolu 2018年2月6日
5  * @todo :产品接口
6  */
7 public interface Product {
8     // ...... 工厂模式中,工厂主要用于产生产品,并不涉及产品的操作,因此此处省略具体产品的操作
9 }
1 package simplefactory;
2 
3 /**
4  * @author : xiaolu 2018年2月6日
5  * @todo   : 产品A
6  */
7 public class ProductA implements Product {
8 
9 }
package simplefactory;

/**
 * @author : xiaolu 2018年2月6日
 * @todo   : 产品B
 */
public class ProductB implements Product {

}
 1 package simplefactory;
 2 
 3 /**
 4  * @author : xiaolu 2018年2月6日
 5  * @todo   : 简单工厂
 6  */
 7 public class Factory {
 8     // 返回值为产品接口
 9     public Product get(int i) {
10         if (i == 0) {
11             // 返回具体的产品(有依赖)
12             return new ProductA();
13         } else if (i == 1) {
14             // 返回具体的产品(有依赖)
15             return new ProductB();
16         } else {
17             throw new RuntimeException("不支持");
18         }
19     }
20 }
 1 package simplefactory;
 2 
 3 /**
 4  * @author : xiaolu 2018年2月6日
 5  * @todo   : 客户端
 6  */
 7 public class Main {
 8     public static void main(String[] args) {
 9         Factory f = new Factory();
10         // 客户端不知道(不依赖)具体产品
11         Product p = f.get(1);
12         // 执行p的操作
13     }
14 }

对比类图和代码实现,应该从结构上很容易区分两者。更重要的是:策略模式是行为型模式,而工厂模式是创建型模式!通俗的说,工厂模式只负责产生“按你所需”的产品,至于你如何使用,工厂是无知的(这也是我为什么没有在产品接口中定义方法,因为不固定)。而策略模式中,具体的策略类是客户端“知道”的(这也是是否需要直接使用策略模式的一个选择【也可以规避它-策略+工厂】),而Context则负责“转发”(只是转发吗?)这里不妨想想,为什么需要Context,如果没有Context会如何呢?如果没有:

1 Strategy strategy = new StrategyA();
2 strategy.algorithm();

好像还反而简单了?Context是Strategy和Main(客户端)之间的一个间接层,可以用来封装需要传递给Strategy的数据结构和参数。

 技术分享图片

  相对于普通的多态结构,策略模式强调的是【算法】的可相互替代性。再次强调:如果具体策略类并不复杂就不要用策略模式(自找烦恼)。而策略类的一个弊端:客户端类需要“知道”具体策略类------可以通过加一个工厂解决。简单工厂的意义是什么呢? 符合SRP,单一职能,降低耦合 ,还有一个作用---------转换。大部分的if....else代码我们并不能规避,只是从“这里”移到了“那里”,好处是代码更明确,更清晰,更容易扩展,而简单工厂做这种转换非常的合适。- -

 

策略模式(java)

标签:名称   代码结构   ati   class   上下文   设计   image   body   解决   

原文地址:https://www.cnblogs.com/xiao-lu/p/8424665.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!