[设计模式] 策略模式 (Strategy Pattern)

什么是策略模式?

根据《设计模式之禅》的定义:

定义一组算法,并把这些算法封装起来,然后使它们可以互换

这里的算法我们可以理解为类处理某个业务的方法,而我们都知道,处理同一个业务可能会有不同的策略。

为什么要用策略模式?

如策略模式的定义所言,这种模式会把处理某个业务的不同方法封装成不同的类,然后可以根据调用者的状态选择合适的策略。调用者也可以随时切换到不同的模式下,但不改变业务类本身的代码。
下面举一个旅游的例子,根据我们的预算可以选择不同的出行方式,比如高铁、飞机、自驾游……如果没有策略模式,我们大概会有这么一个类

public class Travel {
	private int budget;
	
	public Travel(int budget) {
		this.budget = budget;
	}
	
	public void go() {
		if (budget < 500) {
			System.out.println("坐高铁……");
		} else if (budget>=500 && budget < 1000) {
			System.out.println("自驾游……");
		} else {
			System.out.println("坐飞机……");
		}
	}

	public static void main(String[] args) {
		Travel travel = new Travel(500);
		travel.go();
	}
}

上面这段代码里,travel类中有太多的if else判断,但其实这个预算的判断不应该是这个类的职责,这个类只需要负责旅游出行的相关逻辑就可以了,而决定用哪种出行方式是调用者(main函数)去决定的东西。而你会发现这段代码很难提取到调用者中。
这时候就需要策略模式了。

如何应用策略模式?

首先,策略模式中有三个固定的角色,分别是:

  • Strategy Implements(策略具体实现):对不同算法进行封装
  • Context(上下文对象):屏蔽高层模块对策略对象的直接访问
  • Strategy Interface(策略接口):不同策略的共同接口,负责衔接Context和策略具体实现。

那么我们用策略模式重新设计上面的代码就会由这三部分构成

Strategy Inteface

public interface TravelWayStrategy{
	// 负责提供具体策略实现类的接口
	void go();
}

Strategy Implements

public class HighSpeedRailStrategy implements TravelWayStrategy {
	public HighSpeedRailStrategy() {
		// constructor code
	}
	
	@Override 
	public void go() {
		System.out.println("坐高铁……");
	}
}

public class PlaneStrategy implements TravelWayStrategy {
	public PlaneStrategy() {
		// constructor code
	}
	
	@Override 
	public void go() {
		System.out.println("坐飞机……");
	}
}

public class SelfDrivingStrategy implements TravelWayStrategy {
	public SelfDrivingStrategy() {
		// constructor code
	}
	
	@Override 
	public void go() {
		System.out.println("自驾游……");
	}
}

Context

public class Travel {
	TravelWayStrategy strategy;
	
	public void setStrategy(TravelWayStrategy strategy) {
		this.strategy = strategy;
	}
	
	public void go() {
		strategy.go();
	}
}

然后在调用者就可以根据自己的预算选择不同的出行方式了

public class Test {
	public static void main(String[] args) {
		int budget = 500;
		Travel travel = new Travel();
		
		if (budget < 500) {
			travel.setStrategy(new HighSpeedRailStrategy());
		} else if (budget>=500 && budget < 1000) {
			travel.setStrategy(new SelfDrivingStrategy());
		} else {
			travel.setStrategy(new PlaneStrategy());
		}
		
		travel.go();
	}
}

上面的代码我们就把budget判断和travel出行类解耦了,由调用者来确定出行方式,travel出行类只需要用我们指定好的出行方式完成自己分内职责就好了。

总结

一个算法接口,任意个实现了算法接口的具体实现类和一个持有算法接口对象的上下文对象,就能实现策略模式。

当然我们也必须承认策略模式也有不足的地方:

  1. 调用类必须知道所有可选择的策略的具体实现类以及它们之间的区别,以便能选择合适的策略。换言之,策略模式只适用于调用者知道具体的算法的实现类的情况。
  2. 如果备选的策略实现类很多的话,对象的数目会很可观。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值