`

设计模式之策略模式

 
阅读更多

策略(Strategy)模式:

       策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

 

       假设现在要设计一个贩卖各类书籍的电子商务网站的购物车(Shopping Cat)系统。一个最简单的情况就是把所有货品的单价乘上数量,但是实际情况肯定比这要复杂。比如,本网站可能对所有的教材类图书实行每本一元的折扣;对 连环画类图书提供每本7%的促销折扣,而对非教材类的计算机图书有3%的折扣;对其余的图书没有折扣。由于有这样复杂的折扣算法,使得价格计算问题需要系统地解决。

 

       使用策略模式可以把行为和环境分割开来。环境类负责维持和查询行为类,各种算法则在具体策略类 (ConcreteStrategy)中提供。由于算法和环境独立开来,算法的增减、修改都不会影响环境和客户端。当出现新的促销折扣或现有的折扣政策出 现变化时,只需要实现新的策略类,并在客户端登记即可。策略模式相当于"可插入式(Pluggable)的算法"。

二、 策略模式的结构

 

      策略模式是对算法的包装,是把使用算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:"准备一组算法,并将每一个算法封装起来,使得它们可以互换。"

 

策略又称做政策(Policy)模式【GOF95】。下面是一个示意性的策略模式结构图:

 

 

 

 这个模式涉及到三个角色:

 

  • 环境(Context)角色:持有一个Strategy类的引用。
  • 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
  • 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。

三、代码例子:

还是拿发送消息的例子,

 

//发送消息的接口
public interface ISender {
	public void send();
}
//发送Mail消息,等价于一系列算法的其中之一
public class MailSender implements ISender {
	@Override
	public void send() {
		System.out.println("发送邮件");
	}
}
//发送PUSH消息,等价于一系列算法的其中之一
public class PushSender implements ISender {
	@Override
	public void send() {
		System.out.println("发送Push");
	}
}
//发送Sms消息,等价于一系列算法的其中之一
public class SmsSender implements ISender {
	@Override
	public void send() {
		System.out.println("发送短信");
	}
}

 

//选择不同发送方式的上下文,等价于选择不同算法的上下文
public class SendContext {
	private ISender sender;

	public ISender getSender() {
		return sender;
	}

	public void setSender(ISender sender) {
		this.sender = sender;
	}
        //ISender接口传递到上下文中,由上下文决定由哪个发送
	public SendContext(ISender sender) {
		this.sender = sender;
	}
	
	public void sendMessage() {
		this.sender.send();
	}
}

 

 

 

 

四、在什么情况下应当使用策略模式

 

在下面的情况下应当考虑使用策略模式:

 

       1. 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

 

       2. 一 个系统需要动态地在几种算法中选择一种。那么这些算法可以包装到一个个的具体算法类里面,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算 法类均有统一的接口,由于多态性原则,客户端可以选择使用任何一个具体算法类,并只持有一个数据类型是抽象算法类的对象。

 

       3. 一个系统的算法使用的数据不可以让客户端知道。策略模式可以避免让客户端涉及到不必要接触到的复杂的和只与算法有关的数据。

 

       4. 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并体现面向对象设计的概念。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics