策略模式
生活中我们去超市购物可以选择不同促销价格的商品,去旅游可以选择可以坐汽车、可以坐火车、可以坐飞机。
策略模式:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换
策略模式具体角色实现
- 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
- 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为。
- 环境(Context)类:持有一个策略类的引用,最终给客户端调用。
1.创建一个接口
public interface Strategy {
void show();
}
2.创建实现接口的实体类
public class StrategyA implements Strategy{
@Override
public void show() {
System.out.println("满300-40");
}
}
public class StrategyB implements Strategy{
@Override
public void show() {
System.out.println("满500打8折");
}
}
public class StrategyC implements Strategy{
@Override
public void show() {
System.out.println("买一送一");
}
}
3.创建 Context类
public class Context {
private Strategy strategy;
public Context(Strategy strategy)
{
this.strategy=strategy;
}
public void ContextShow()
{
strategy.show();
}
}
使用 Context 来查看当它改变策略 Strategy 时的行为变化
public static void main(String[] args) {
Context context=new Context(new StrategyA());
context.ContextShow();
}
策略模式实现
以淘宝618促销为例使用策略模式实现促销打折场景
商品满300-40,打八折,正常收费
1.声明收费接口
public interface Cash{
double Calculation(double money);
}
2.声明上下文类
public class Context {
private Cash cash;
public Context(Cash cash)
{
this.cash=cash;
}
public double ContextShow(double money)
{
return cash.Calculation(money);
}
}
3.声明正常收费子类
public class CashNormal implements Cash{
@Override
public double Calculation(double money) {
double total=0;
total=money;
System.out.println("正常收费,金额"+total);
return total;
}
}
4.声明打折类
public class CashDiscount implements Cash{
private double disCount;
public CashDiscount(double disCount)
{
this.disCount=disCount;
}
@Override
public double Calculation(double money) {
double total=0;
total=money*disCount;
System.out.println("参加打"+disCount+"折活动,金额"+total);
return total;
}
}
5.声明满减类
public class CashFullreduction implements Cash{
//满减金额
private double moneyReturn;
//满减门槛
private double moneyConditation;
public CashFullreduction(double moneyReturn,double moneyConditation)
{
this.moneyConditation=moneyConditation;
this.moneyReturn=moneyReturn;
}
@Override
public double Calculation(double money) {
double total=0;
if(money<300){//如果金额小于300,不满减
total=money;
}
else
{
total= money-(Math.floor(money/moneyConditation)*moneyReturn);
}
System.out.println("支付"+money+"元,满"+moneyConditation+"减"+moneyReturn+",最后金额为"+total);
return total;
}
}
6.客户端
public static void main(String[] args) {
Context context=new Context(new CashFullreduction(40,300));//满300-40
context.ContextShow(400);
Context context2=new Context(new CashDiscount(0.8));//打八折
context2.ContextShow(400);
Context context3=new Context(new CashNormal());//正常收费
context3.ContextShow(400);
}
总结
1.优点
-
策略类之间可以自由切换
由于策略类都实现同一个接口,所以使它们之间可以自由切换。
-
易于扩展
增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“
-
避免使用多重条件选择语句(if else),充分体现面向对象设计思想。
2.缺点:
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
- 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。
使用场景:
1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为
2、一个系统需要动态地在几种算法中选择一种
3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现