Strategry模式简单理解及应用

本文介绍如何使用设计模式中的策略模式来构建可扩展的CSV文件解析算法,通过定义接口和继承策略类,实现了算法的灵活替换,提高了代码的复用性和可维护性。

喜欢设计模式,第一次在实践中主动想到运用设计模式,就记下自己的理解及实现,虽然非常简单。

我的理解,多态是类的泛化,Stategy模式是方法的泛化。这就为替换不同算法提供了方便。替换的可能,就是现在不把语句写死。白猫黑猫,抓住耗子是好猫。我们只需要下命令:“去抓耗子!”具体是白猫抓还是黑猫抓,我们暂时不考虑;因为即使现在定死了,将来也可能变。软件开发的最大问题——变,就迫使我们“下命令”时不能多说一点;只要多说了一点现在确定不了的,将来就很可能错(说话和写程序一个道理。。)。

不把语句写死”的方法就是定义接口,利用多态性,把刚创建对象的对象赋给父接口的引用。以后用这个接口的引用来操作这个对象,就相当于只针对此对象的一方面特性对其进行操作。比如一个对象是一个人叫王二,他如果在打酱油时被临时拉去,演一个1秒钟就死了的一个小喽啰,剧本里不可能写“王二一命呜呼”,只会写“一个小喽啰一命呜呼”。因为他如果2秒钟才死,肯定被踢走,揪来另一个打酱油的替他演。剧本只指定当前情景下的角色,不多定义一点儿。多态性就是这样,用一种特性(即接口)来操作对象。从王二这个例子,可见多态性的应用多么重要。

功能是解析CSV文件,构建EarEntry对象。考虑到CSV文件中的属性可能的变化,需要可扩展算法;针对包含不同属性的CSV文件,构建不同类型的EarEntry(即EarEntry的子类)。

这个GisImpl类中的csvToDB()方法,就是需要构建EarEntry对象的地方。采用Strategry模式的思想,也是很自然的想法,主要就两步:用BuildWay来创建一个Builder,然后此Builder执行build()方法构建出EarEntry对象。

public class GisImpl implements GisFacade{
	private EarEntryBuildWay earEntryBuildWay;

	@Override
	public String csvToDB(byte[] csvBytes) {
				//......
				//......				
				EarEntryBuilder earEntryBuilder = 
						new EarEntryBuilder(this.earEntryBuildWay);
				EarEntry earEntry = earEntryBuilder.build(attributeStrs); 	
	}
}

下面来写这两步中的接口和类。首先为了考虑算法的泛化,需要一个接口,其中包含泛化的方法:定义构建EarEntry的方法——EarEntryBuildWay接口,其中包含了buildEarEntry()方法。从命名就可以看出,这个接口和其方法都没有表明一种具体的build的方式(如果是buildWay1、buidlWay2就是两种不同的方式)。

public interface EarEntryBuildWay {
	public EarEntry buildEarEntry(String[] attributeStrs);
} 

有了这个泛化的接口,我们就可以通过继承它来扩展不同的算法了。下面这个类EarEntryBuildWay1就提供了一种具体的算法。


public class EarEntryBuildWay1 implements EarEntryBuildWay{
	
	@Override
	public EarEntry buildEarEntry(String[] attributeStrs) {
		EarEntry earEntry = new EarEntry();
		earEntry.setTime(attributeStrs[0]);
		earEntry.setMs(attributeStrs[1]);
		earEntry.setMag(attributeStrs[2]);
		earEntry.setLocation(attributeStrs[3]);
		earEntry.setLog(attributeStrs[4]);
		earEntry.setLat(attributeStrs[5]);
		earEntry.setDepthKm(attributeStrs[6]); 
		earEntry.setDepthMi(attributeStrs[7]);
		earEntry.setUtc(attributeStrs[8]);
		return earEntry;
	}

}

如果要使用这种方法来build,这里用了Spring的依赖注入。在配置文件applicationContext.xml中,

ref="earEntryBuildWay1"
只要把ref的值改变,就可以随意替换代表不同build方法的子类。也就是说,除了写新的算法类继承接口外,只需要改这个xml文件中的一个属性,就实现了算法的改变。Java代码不需要任何修改,也就不会影响其他的代码。

	<bean id="gis" class="org.springframework.samples.jpetstore.domain.logic.GisImpl">
		<property name="passageDao" ref="passageDao"/>
		<property name="earEntryDao" ref="earEntryDao"/>
		<property name="earEntryBuildWay" ref="earEntryBuildWay1"/>		
	</bean>
	
	<bean id="earEntryBuildWay1" class="org.springframework.samples.jpetstore.util.EarEntryBuildWay1">
	</bean>

有了算法(BuildWay),还要有个执行它的主体。下面就是执行算法的主体EarEntryBuilder,它包含私有成员earEntryBuildWay,也就是表示构造者有一个构造的方法。Get/Set方法自不必说,构造子的参数是EarEntryBuildWay类型,可理解为有了算法就有了构造者。build()方法包裹了泛化的构造方法,也就是利用自身算法来完成构建。

public class EarEntryBuilder {
	private EarEntryBuildWay earEntryBuildWay;

	public EarEntryBuildWay getEarEntryBuildWay() {
		return earEntryBuildWay;
	}

	public void setEarEntryBuildWay(EarEntryBuildWay earEntryBuildWay) {
		this.earEntryBuildWay = earEntryBuildWay;
	}
	
	public EarEntryBuilder(EarEntryBuildWay earEntryBuildWay){
		this.earEntryBuildWay = earEntryBuildWay;
	}
	public EarEntry build(String[] attributeStrs){
		return this.earEntryBuildWay.buildEarEntry(attributeStrs);
		
	}
}


以上就运用Strategry模式解决了一个非常简单的问题。前两天看到有个牛人说,好的程序员,不封装,也没有重复代码。我觉得对于编程天才来说,也许确实不需要什么设计模式;但是随着项目规模的扩大,先不说设计模式的技术上的必要性,人力规模将会大大增加。这时大多数人不是编程天才,就需要松耦合来进行分工。所以我觉得设计模式是非常有必要学习的,也是很有意思的一种编程方式,很贴近现实生活中的道理。



(参考

http://www.jdon.com/designpatterns/designpattern_Strategy.htm

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值