设计模式学习笔记(六)之策略模式(Strategy)
(一):策略模式的定义:
它定义了算法家族,分别封装起来,让他们之间可以相互替换,这个模式让算法的变化,不会影响到使用的用户。
(二):策略模式体现了两个 最基本的面向对象的原则:
- 编程中使用接口,面向接口编程.
- 封装变化
- 抽象策略角色:策略类,通常由一个接口或者抽象类实现;
- 具体策略角色:封装了相关的算法和行为;
- 环境角色:持有一个策略类的引用,然后我们客户端可以去调用;
![](https://img-my.csdn.net/uploads/201204/05/1333637153_2046.png)
使用策略模式,我们这对一组算法,可以去把每一个算法封装到具有共同接口的独立的类中,这样我们可以进行相互退换了。这样算法可以再不影响客户端调用的情况下去发生改变,这样可以把行为和环境进行分开来。算法的具体实现是在具体策略类中。
(六):下面我们来自己模拟实现一个策略模式(首先看下例子的结构图)
①:抽象策略角色:Strategy.java
package com.jiangqq.strategy;
//抽象策略角色:接口
//定义了所有具体的策略角色的公共算法接口
public interface Strategy {
public int calculate(int a,int b);
}
②:具体策略角色:AddStrategy.java,ReduceStrategy.java,MultiplyStrategy.java,DivideStrategy.java
package com.jiangqq.strategy;
//具体策略类:加法策略的实现类
public class AddStrategy implements Strategy {
@Override
public int calculate(int a, int b) {
return a+b;
}
}
package com.jiangqq.strategy;
//具体策略类:减法策略的实现类
public class ReduceStrategy implements Strategy {
@Override
public int calculate(int a, int b) {
// TODO Auto-generated method stub
return a-b;
}
}
package com.jiangqq.strategy;
//具体策略类:乘法策略的实现类
public class MultiplyStrategy implements Strategy {
@Override
public int calculate(int a, int b) {
// TODO Auto-generated method stub
return a*b;
}
}
package com.jiangqq.strategy;
//具体策略类:除法策略的实现类
public class DivideStrategy implements Strategy {
@Override
public int calculate(int a, int b) {
// TODO Auto-generated method stub
return a/b;
}
}
③:环境角色:Context.java
package com.jiangqq.strategy;
//环境角色,持有策略类的引用,去调用该具体策略类的算法
//给客户端去进行调用
public class Context {
//定义策略角色的引用,通过Context的构造函数传进去
private Strategy mStrategy;
public Context(Strategy pStrategy) {
this.mStrategy = pStrategy;
}
//具体策略角色去实现算法
public int calculate(int a,int b)
{
return mStrategy.calculate(a, b);
}
}
④:Client测试类:
package com.jiangqq.strategy;
//客户端测试实例代码
public class Client {
public static void main(String[] args) {
//使用加法的策略
Context context=new Context(new AddStrategy());
System.out.println(context.calculate(1, 2));
//使用减法的策略
context=new Context(new ReduceStrategy());
System.out.println(context.calculate(1, 2));
//使用乘法的策略
context=new Context(new MultiplyStrategy());
System.out.println(context.calculate(1, 2));
//使用除法的策略
context=new Context(new DivideStrategy());
System.out.println(context.calculate(1, 2));
}
}
测试结果:
(七):这样的策略模式的缺点:
我们必须要知道所有的策略类,并且要我们自己去决定要去使用哪个策略类,而且这样会存在大量的策略类
为了尽可能的消除这些缺点,我们可以使用策略模式加简单工厂模式的方法来进行实现
(点击进入:工厂模式)
这时我们需要去改变一下
①:环境角色类:Context.java
package com.jiangqq.factory;
//在进行创建ContextFactory对象的时候,传入type值进行,根据不同的值,
//工厂类会进行创建出对象的策略类
//1:加法策略类 2:减法策略类 3:乘法策略类 4:除法策略
import com.jiangqq.strategy.AddStrategy;
import com.jiangqq.strategy.DivideStrategy;
import com.jiangqq.strategy.MultiplyStrategy;
import com.jiangqq.strategy.ReduceStrategy;
import com.jiangqq.strategy.Strategy;
//这是生成不同具体策略类的工程类
public class ContextFactory {
Strategy mStrategy=null;
public ContextFactory(int type)
{
switch (type) {
case 1:
//1:加法策略类
mStrategy=new AddStrategy();
break;
case 2:
// 2:减法策略类
mStrategy=new ReduceStrategy();
break;
case 3:
// 3:乘法策略类
mStrategy=new MultiplyStrategy();
break;
case 4:
//4:除法策略
mStrategy=new DivideStrategy();
break;
}
}
public int calculate(int a,int b)
{
return mStrategy.calculate(a, b);
}
}
②:客户端测试类:
package com.jiangqq.factory;
//在进行创建ContextFactory对象的时候,传入type值进行,根据不同的值,
//工厂类会进行创建出对象的策略类
//1:加法策略类 2:减法策略类 3:乘法策略类 4:除法策略
public class Client {
public static void main(String[] args) {
//进行加法的策略
ContextFactory contextFactory=new ContextFactory(1);
System.out.println(contextFactory.calculate(1, 2));
//进行减法的策略
contextFactory=new ContextFactory(2);
System.out.println(contextFactory.calculate(1, 2));
//进行乘法的策略
contextFactory=new ContextFactory(3);
System.out.println(contextFactory.calculate(1, 2));
//进行除法的策略
contextFactory=new ContextFactory(4);
System.out.println(contextFactory.calculate(1, 2));
}
}
//在进行创建ContextFactory对象的时候,传入type值进行,根据不同的值,
//工厂类会进行创建出对象的策略类
//1:加法策略类 2:减法策略类 3:乘法策略类 4:除法策略,此时根据不同的策略类去调用的算法,实现不同的行为.
使用策略模式,我们简化测试,因为每个算法都是在定义具体的类中,可以进行单独的测试。策略模式是用来封装算法并且可以封装任何类型的行为,所有在使用中如果要在不同的时间要去应用不同的规则,那我们可以去使用策略模式实现.
代码下载链接地址:http://download.csdn.net/detail/jiangqq781931404/4202470