【设计模式】策略模式

定义

定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。【维基百科】

起源

在一个系统中,针对同一种行为,需要针对不同的情况有各自具体的实现,这时,如果不采用一种比较好的设计模式的话,会出现许多if…else(if)语句,为了避免这种情况的发生,于是就有了策略模式。

类图

策略模式类图
说明

  • Stategy    策略,也就是上文提到的行为
  • ConcreteStrategy    具体的策略角色,即每一种行为的具体实现
  • Context    角色,要去执行这些行为的对象,在这个类中,会将抽象的行为注入进去,即Stategy,在执行行为的时候,会根据具体的子类对象去执行对应的行为。
case

员工每天早上去上班,不同的人,上班的时间点和采用的交通方式也不一样,住的远的人,7点就要出发了,坐公交或者自驾,住的近的人,可能7点30分才出发,骑自行车或者电动车,如果在没有使用策略模式之前,代码是这样实现的:

package com.steven.cn.simple;

public class Test1 {
	
	/**
	 * 枚举,为了测试方便
	 * @author Steven
	 *
	 */
	private enum Type {
		FAR("FAR", "住的远的人"), NEAR("NEAR", "住的近的人");
		private String value;
		private String valueName;
		private Type(String value, String valueName) {
			this.value = value;
			this.valueName = valueName;
		}
	}
	
	/**
	 * 行为
	 * @param type
	 */
	public static void goCompany(String type) {
		if(Type.FAR.value.equals(type)) {
			System.out.println("每天7点钟从家出发,坐公交或者自驾");
		}else if(Type.NEAR.value.equals(type)) {
			System.out.println("每天7点30分从家出发,骑自行车或者电动车");
		}
	}

	public static void main(String[] args) {
		goCompany(Type.FAR.value);
	}
}

如果采用策略模式的话,会变成下面这种方式:
首先会有一个抽象的行为类,一般是采用接口,可以多实现

package com.steven.cn.stategy;

/**
 * 策略类
 * @author Steven
 *
 */
public interface IStategy {

	public void goCompany();
}

行为的具体实现,因为有不同的实现方式,所以会有多个类

package com.steven.cn.stategy.impl;

import com.steven.cn.stategy.IStategy;

/**
 * 住的远的人的行为实现类
 * @author Steven
 *
 */
public class ConcreteStrategyA implements IStategy{

	@Override
	public void goCompany() {
		System.out.println("每天7点钟从家出发,坐公交或者自驾");
	}

}
package com.steven.cn.stategy.impl;

import com.steven.cn.stategy.IStategy;

/**
 * 住的近的人的行为实现类
 * @author Steven
 *
 */
public class ConcreteStrategyB implements IStategy{

	@Override
	public void goCompany() {
		System.out.println("每天7点30分从家出发,骑自行车或者电动车");
	}

}

最后会有一个角色类,这个类会决定行为的具体实现方式

package com.steven.cn.context;

import com.steven.cn.stategy.IStategy;

public class Employee {

	private IStategy stategy;

	public Employee(IStategy stategy) {
		this.stategy = stategy;
	}
	
	public IStategy getStategy() {
		return stategy;
	}

    // 这里提供set方法,是为了多一种方式封装角色,可以只使用构造方法来封装角色。
	public void setStategy(IStategy stategy) {
		this.stategy = stategy;
	}

	public void execGoCompany() {
		stategy.goCompany();
	}
}

测试类

package com.steven.cn;

import com.steven.cn.context.Employee;
import com.steven.cn.stategy.impl.ConcreteStrategyA;
import com.steven.cn.stategy.impl.ConcreteStrategyB;

public class Test {

	public static void main(String[] args) {
		Employee employee;
		
		// 住的远的人
		employee = new Employee(new ConcreteStrategyA());
		employee.execGoCompany();
		System.out.println("--------------");
		// 住的近的人
		employee = new Employee(new ConcreteStrategyB());
		employee.execGoCompany();
		System.out.println("--------------");
		
		employee.setStategy(new ConcreteStrategyA());
		employee.execGoCompany();
		System.out.println("--------------");
	}
}

最后的输出结果是

结果自己运行一下就知道了。。。

END

通过上面两种情况下代码的对比,优缺点很明显了

优点:
  1. 避免使用繁杂的if...else(if)语句进行判断
  2. 行为的具体实现方式可以自由的切换,通过封装不同的角色就可以实现不同的行为
  3. 扩展性高,增加一种行为的实现方式,只需要实现接口即可
缺点
  1. 类增多了,每添加一个行为的具体实现,就多出一个类出来
  2. 所有的实现方式都必须告诉别人,这样别人才能决定使用哪个策略角色

源码下载地址: 源码下载地址
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值