喜欢设计模式,第一次在实践中主动想到运用设计模式,就记下自己的理解及实现,虽然非常简单。
我的理解,多态是类的泛化,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)
本文介绍如何使用设计模式中的策略模式来构建可扩展的CSV文件解析算法,通过定义接口和继承策略类,实现了算法的灵活替换,提高了代码的复用性和可维护性。
589

被折叠的 条评论
为什么被折叠?



