策略模式

1.策略模式是什么

1.百度百科

策略模式是指对一系列的算法定义,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

2.维基百科

In computer programming, the strategy pattern (also known as the policy pattern) is a behavioral software design pattern that enables selecting an algorithm at runtime. The strategy pattern
defines a family of algorithms,
encapsulates each algorithm, and
makes the algorithms interchangeable within that family.
Strategy lets the algorithm vary independently from clients that use it.[1] Strategy is one of the patterns included in the influential book Design Patterns by Gamma et al. that popularized the concept of using design patterns to describe how to design flexible and reusable object-oriented software.

3.楼主的理解

定义了一组实现,将其分装起来。并且可以使他们互相替换。说白了就是为一个需求准备了多个实现,在具体用的时候按需挑选实现。

4.核心角色

策略管理角色(context) 也叫上下文角色,屏蔽高层模块对具体实现的访问,分装可能的变化

抽象策略角色 对每一个具体实现进行分装,通常定义为接口,定义了个功能必要的方法和属性。

具体策略角色 实现抽象策略定义的具体实现类,有多个实现具体使用时候选择。

2.策略模式解决了什么问题

  1. 解除耦合: 策略模式完美的支持了“开闭原则”,用户可以在不修改原有基础系统的基础上选择实现方式,也可以灵活增加新的实现。简单说就是一个算法的增加改动并不会影响其他算法。
  2. 有效的实现类管理: 提供了多种相同接口的实现的管理办法。由于存在一个策略管理类的角色,具体策略角色调用方式集中。
  3. 替换继承关系: 提供了一种可以替换继承关系的办法。
  4. 替换多重条件转移: 避免了使用多重条件转移语句。

3.策略模式用法

1.概述

下面我们用代码来实现策略模式
抽象策略角色

/**
 * 策略抽象类
 * @author yanlong
 *
 */
public interface Strategy {

	//策略方法
	void strategyMethod();
}

具体策略角色


public class FirstStrategy implements Strategy {

	@Override
	public void strategyMethod() {
		System.out.println("执行了第一个策略");
	}

}

public class SecondStrategy implements Strategy {

	@Override
	public void strategyMethod() {
		System.out.println("执行了第二个策略");
	}

}

策略管理角色

public class Context {
	//持有一个具体的策略对象
	private Strategy strategy;
	//构造上下文时传入一个具体对象
	public Context(Strategy strategy) {
		this.strategy = strategy;
	}
	//调用该策略的方法
	public void strategyMethod() {
		strategy.strategyMethod();
	}
}

客户端调用策略

public class Customer {

	public static void main(String[] args) {
		Strategy firstStrategy = new FirstStrategy();
		Context context = new Context(firstStrategy);
		context.strategyMethod();
		Strategy secondStrategy = new SecondStrategy();
		context = new Context(secondStrategy);
		context.strategyMethod();
	}

}

结果

执行了第一个策略
执行了第二个策略

2.具体的实现以及对策略模式的改良

由于策略模式的问题在于如果调用方并不知道具体实现有哪些从而曹成了创建实例困难。需要使用简单工厂模式配合。

下面我就以超市收银打折为例子,举例说明策略模式+简单工厂模式配合解决问题。

抽象策略角色

/**
 * 打折接口
 * 定义打折算法
 */
public interface Discount {

	//打折方案
	Double discountAmount(Double amount);
}

具体策略角色


public class DISCOUNT300SUB100 implements Discount {
	@Override
	public Double discountAmount(Double amount) {
		return amount >=300? amount-100:amount;
	}
}

public class Discount20Off implements Discount {

	@Override
	public Double discountAmount(Double amount) {
		return amount*0.8;
	}

}

策略管理者+简单工厂

public class CashierCenter {

	public final static int DISCOUNT_20_OFF = 1;
	public final static int DISCOUNT_300_SUB_100 = 2;

	private Discount discount;


	public CashierCenter(int type) {
		switch(type) {
		case DISCOUNT_20_OFF:
			discount = new Discount20Off();
			break;
		case DISCOUNT_300_SUB_100:
			discount = new DISCOUNT300SUB100();
			break;
		default:
			discount = new DiscountNormal();
		}
	}

	public Double cashier(Double amount) {
	 	return discount.discountAmount(amount);
	}
}

调用方

public class Customer {

	public static void main(String[] args) {
		CashierCenter cc = new CashierCenter(CashierCenter.DISCOUNT_20_OFF);
		Double amt = cc.cashier(250D);
		System.out.println(amt);
		cc = new CashierCenter(CashierCenter.DISCOUNT_300_SUB_100);
		amt = cc.cashier(450D);
		System.out.println(amt);
	}

}

管理者内部维护了一个常量 只需按照常量创建对应算法实例即可。这么做就完全不需要暴露内部算法实例,甚至不需要暴露算法接口。只需要一个管理类就能自由创建相应算法对象。

4.策略模式的问题

  1. 实现类的暴露: 调用的客户点必须知道所有的策略类,并自行决定使用哪个策略类。也就是客户端必须知道所有实现类的区别以及使用场景。可以通过工厂方法模式、代理模式去修正。
  2. 策略实现类泛滥: 策略模式将产生过多的策略类.由于策略模式基本无法复用,任何细小的变化都将封装成一个新的策略实现类。

5.策略模式总结

策略模式强调的是整体的替换,接口的每一个实现都是一个完整的整体。变化的是实现的整体流程。
策略模式应用场景如下:

  1. 多个类的分别只是在于行为不同
  2. 你需要对行为的算法做很多变动
  3. 客户不知道算法要使用的数据

所以策略模式使用在实现类整体大规模变动的情况下。

posted @ 2018-01-29 11:38  枫飘雪落  阅读(356)  评论(0编辑  收藏  举报