设计模式之策略模式(fyun之我见系列二)

fyun之我见之策略模式

提及策略模式,我这里就不得不先对简单工厂模式在什么情况下使用,只有先说清楚简单工厂模式及策略模式的使用情况我们才能在看策略模式下不会迷糊。
简单工厂的一般使用满足以下情况:
1:满足一系列产品(对象)都含有一些共同的特征。
2:满足该系列产品(对象)仅对它们共同的特征有不同的表现形式。
从上面两个条件我们可以知道简单工厂模式的优缺点:
优点:
客户端直接创建统一的基类(父类)来实现其不同子类的方法来达到 对责任的分割
缺点:
1. 工厂类只有其基类(父类)是调用的,难以应变复杂,多层等奖的结构。其次基类(父类)一旦不能正常工作,将影响整个系统的正常运行。
2. 系统扩展困难,当添加新产品 对象),就不得不修改工厂类的逻辑,导致逻辑过于复杂。

策略模式的条件其实和简单工厂模式差不多,这里它和简单工厂模式主要区别在于:

1: 针对工厂的子类,它可能需要在不同情况下采用不同的策略(算法)。(如果用简单工厂模式,我们只能扩充一个子类来完成,而策略模式则在这方面做了支持,就是子类的算法可以针对不同情况而重复使用。听起来好像子类也是个包含子类的节点类,其实不然,在策略模式下,子类的创建时支持一类相同算法情况下而成立的。比如:一个商品需要打折,它无外乎就是8折、7.5折等一个RATE类而已。(不知道大家明白了不,不明白也没关系,接下来我将举例来解读)
2:用户(客户)需要对具体策略进行隐藏。

一:策略模式之解读:
策略模式就是定义一系列算法的方法的对象集合(或一类集合)。
解读: 简单说就是类似简单工厂一样,存在一系列具有公共特征的子类的集合,但是这些子类中存在一些(可以是一个或全部)子类提供的算法是用来完成相同的工作,只是由于条件变化而导致使用不同。

二:针对面试
我们常常在面试中会被问到OO开发中的内聚和耦合问题,那么,我们的策略模式就是一种高内聚,低耦合的设计模式。(当然之间谈到的简单工厂也是降低耦合的方法,但是,我们拿策略模式来展开对耦合的解读,我想应该是个不错的展现自己对OO开发的理解)。

三:举例

题目:这里我就以我做过的一个游戏实物奖抽奖(即,针对游戏满足一定的条件后,对满足条件的玩家进行随机抽奖)。

分析问题:
我们抽奖应该不陌生吧,大家首先想到的是,随机把满足条件的玩家全部抽取出来,然后按先后顺序分别派奖不就行了。或者很多人会想,这样不好,还是分开抽比较合理,即我针对每个级别奖项依次随机抽奖,在抽取过程中把命中账号缓存在内存中,然后对新抽出来的账号进行判定,排除重复抽取情况。
以上两种说法都每错,但如果我们需要加入抽奖条件呢?很明显,我们游戏都分有大区,为了达到抽奖分布在不同大区中,我们需要指定大区来抽奖。
其次我们也有可能抽取满足条件的账号的前10或前100等中抽取一等奖(或特等奖)这个也是抽奖过程中需要考虑的问题。etc... 

要的结果:
从上面分析中我们不难看出,同为随机抽奖情况下,所需要的判断条件的改变也将给抽奖带来变化。但一般抽奖都就算是指定前10或100这个变量只是改变抽奖的范围,而他们始终离不开是一类指定范围个数账号的随机方式。

四:例子设计(部分源码):
设计类图:



接下来就开代码了:
public abstract class RandomAward
{ 	
	private int scoreCount;
	public int ScoreCount 
	{
		get { return scoreCount; } 
		set { scoreCount = value; }
	}
	 public virtual void TakeOut
	{ 
		//Nothing To Do.
	}
}
pulic class OrdinaryRandomAward : RandomAward
{
	public override void TakeOut() 
	{
		Random rm = new Random(); ... // 全部随机抽取方法逻辑... 
	}
}
pulic class RegionRandomAward : RandomAward
{
	private string regionName="";
	
	public RegionRandomAward(string _rn)
	{
		this.regionName = _rn;
	}
	
	public override void TakeOut()
	{
		Random rm = new Random();
		... // 指定大区条件随机抽取方法逻辑
		...
	}
}
pulic class RankRandomAward : RandomAward
{
	private int rankFrom=0;
	private int rankTo=0;
	
	public RankRandomAward(int _rf, int _rt)
	{
		this.rankFrom = _rf;
		this.rankTo=_rt;
	}
	
	public override void TakeOut()
	{
		Random rm = new Random();
		... // 约束范围比例随机抽取方法逻辑
		...
	}
}
public class AwardContext
{
	private RandomAward ra;
	public AwardContext(string type)
	{
		switch(type)
		{
			case "全部随机": ra = new OrdinaryRandomAward(); break;
			case "前100": ra = new RankRandomAward(0,100); break;			
			case "第100至500": ra = new RankRandomAward(100,500); break;
			case "指定一区": ra = new RegionRandomAward("一区");break;
			default: throw new Exception('不存在该抽奖策略');
		}
	}
	
	public void BeignTake()
	{
		ra.TakeOut();
	}
}

// 客户端调用
public class A
{
	AwardContext ac=new AwardContext("全部随机");
	ac.BeignTake(); // 就这么简单。哈哈~~~
}


表面看起来好像依然写了不少代码,但如果我们将策略抽出,然后利用反射,想想是不是会达到只需要配置就能够不断支持各种抽奖的方式呀。

我一般是把上一章的开发模式优缺点在下一章展示,以便大家重新回味得到更好的巩固。

下一个我们将介绍三大开发模式原则,

即:单一职责原则、开放——封闭原则、依赖倒转原则。


希望大家多多分享,多多支持。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值