参考链接:http://terrylee.cnblogs.com/archive/2006/01/04/310716.html,大致如下:
public abstract class Log { public abstract void Write(); } public class EventLog : Log { public override void Write() { Console.WriteLine("EventLog Write Success!"); } } public class FileLog : Log { public override void Write() { Console.WriteLine("FileLog Write Success!"); } } //工厂 public abstract class LogFactory { public abstract Log Create(); } public class EventFactory : LogFactory { public override EventLog Create() { return new EventLog(); } } public class FileFactory : LogFactory { public override FileLog Create() { return new FileLog(); } } //调用 static void Main(string[] args) { LogFactory factory = new EventFactory(); Log log = factory.Create(); log.Write(); }
上面的调用代码,没有看出工厂方法的好处,如果 没有工厂,也是一样的调用如下:
static void Main(string[] args) { //LogFactory factory = new EventFactory(); Log log = new EventLog(); log.Write(); }
再 扩展一个Log的话,又要再写一个实现工厂,再通过实现工厂来创建,是不是多此一举,如果反射的话,直接在配置文件中配置相关log就行,何必用工厂。
各位 都说说,解释一下上面的工厂 或者说说 工厂有什么好处?
上面的代码就不看了,我举另外的例子来说明下工厂的好处。假设你写了个类似qq的软件,为了吸引用户用你的软件,只要登录软件就有奖励。最开始你的代码可能是这样的:
void LogOn() { //先做一些验证用户名密码之类的事情 //登录成功之后要给这个用户奖励了,假设奖励100经验 user.Exp += 100; }
由于运作成功,很多人用,有的人还愿意花钱购买VIP,对于VIP当然要身份尊贵一点,奖励也是不同的,那VIP用户除了奖励200经验,还会奖励1个道具,那么如果为了快速完成功能,代码可能是这样的:(还是在LogOn方法里)
if (user.IsVip) { user.Exp += 200; user.Item++; } else { User.Exp += 100; }
将来会员又有了白金会员,黄金会员,钻石会员等等...于是这个if-else不断扩大,或者是一个庞大的switch-case,已经惨不忍睹了...工厂模式:
void LogOn() { //先登录,下面是发奖励 BenefitProvider privider = BenefitProvider.Get(user); provider.GiveBenefit(user); //发奖励 } //BenefitProvider 是一个基类,针对不同的场景返回不同的子类 public abstract class BenefitProvider { public static BeniefitProvider Get(User u) { //例子中不同的奖励机制取决于user,所以传user进来 if (!user.IsVip) return new GeneralBenefitProvider(); else if (!user.IsGoldVip) return new GoldBenefitProvider(); .... } public abstract void GiveBenefit(User u); //子类只要把自己的逻辑实现在这个方法里就可以 } public class GoldBenefitProvider : BenefitProvider { public override void GiveBenefit(User u) { //所有金牌vip的奖励逻辑都在这里集中 u.Exp += 500; u.Items += 5; } }
以上代码已经做到了同一业务逻辑集中,不同业务逻辑分离,已经比较好维护了。相信以上代码已经可以体现工厂的优势。事实上它还有更进一步的优化空间,比如工厂的get方法里(BeniefitProvider.Get)依然有很难看的if或者switch。其实如果分支不是非常多的话已经无伤大雅了,因为逻辑很清晰简单了(如果是按照最先的做法if和else之间,或者case之间有大段大段的逻辑,那才是恐怖),要更完美一点可以用IoC容器来作为工厂,这样只要配置好容器就可以了(无论是通过代码配置还是配置文件来配置,殊途同归)。这个你自己去了解吧,否则展开太多了。
谢谢,感觉 只是把代码 进行分离到不同的方法里, 我还是 要再去理解理解
你去了解一下设计模式的,工厂模式你就清楚了
也不是说多此一举,要根据项目的实际情况来运用
谢谢, 我这就是 在了解啊,不清楚的地方来问大家。
能不能 说说,上面的代码 加了 工厂之后,好处 在哪?
@Qlin:
你上面的这个工厂模式,还没有很大的用处
工厂最大的优势是扩展方便,不需要动主方法,只需要增加扩展类
@Rich.T:
1.扩展的话,如果不用工厂,直接扩展一个子类 File1Log,如果使用工厂,而要 多扩展一个 File1LogFactory。
2.Main方法,如果 改了调用方式,也要改成另一个 子工厂。如果不用工厂,要改另一个调用方式,也是改这里,改成new 另一个log。
没看出扩展 哪里方便? 指点一下,谢谢!
@Qlin:
问题就在这里,你现在是简单工厂,
定义一些配置的话,主方法那里通过接收参数进行调用
@Rich.T:
配置一个 具体的子工厂 和 配置一个具体的Log,有什么区别? 一样可以通过反射,请解释一下,谢谢!
单纯的调用下new确实还不如用反射+配置文件,但如果里面还有些逻辑,是不是就得用工厂方法了?这里面的逻辑现在没有,或许将来就有了,这不就利于扩展了。
谢谢!
有很多 开源项目也用到 工厂方法模式,工厂的逻辑简单,就是创建一个 对象。如果Log里的逻辑变了,子类Log也都的变。 配置文件也可以配置 子类Log。
还是 不太明白 为什么这样做。
工厂模式同样遵循开放封闭原则和高内聚低耦合,一般情况下尽可能在工厂模式不要修改,删除,而是添加功能,这就是所谓扩展性。而好处就在于业务逻辑你在工厂实现,ui层代码不管怎么实现,只是调用这个(接口)“黑匣子”。只需要对工厂处理,就是低耦合了。还有一个显著特点就是移植性强。工厂模式做好了,只需改变ui代码,在web,窗体,控制台,甚至net向java移植都会方便好多。
谢谢,不是很理解,能 来个具体的例子吗
我学习设计模式是从程杰《大话设计模式》学习的,讲的透彻,程杰博客园网址http://www.cnblogs.com/cj723/category/118146.html。你看看把
工厂模式的存在就是要释放new的存在
new log 和 new 工厂 不是一样吗? 是说 反射 ?
@Qlin: 在反射中还是贡献很大的。
Log log = new EventLog();
写代码的的地方跟这个
EventLog 绑定的很死啊。举个极端的例子,你有10地方
用到了EventLog 这个类,以后要是这个类改名,或者是增加了构造函数(取消了默认的构造函数), 这样的话,你就需要修改10个地方,而用了模式,就需要修改一个地方即可。
@chenping2008:
谢谢, 有道理
http://www.cnblogs.com/x-xk/archive/2013/01/06/2830742.html
这篇关于工厂的讲的不错,可以看看把思想理解了也就想通了。
谢谢 去看看
设计模式就的主要目的是方便扩展
如果你的程序只有几百行,而且服务的客户只有一家,业务逻辑也很少发生变化,那不用也没关系
其实就是开闭原则,对扩展开放,对修改封闭!
使用设计模式也是有代价的,就像在你的代码里,如果用工厂模式反会让代码更多,让人感觉“复杂”。。。
但这样的好处是结构清晰,维护方便,一般的小项目压根用不上什么设计模式,只有项目足够大,足够复杂,并且后期会不断完善持续开发,才能体现出设计模式的优势!
对修改“封闭”到底指的什么呢?是绝对不修改任何代码吗?还是只不用修改客户端的调用代码?
谢谢。
你有一个创建水果的工厂,在设计和项目交付给用户使用的时候只考虑了苹果和橘子,但你同时还考虑了会要创建其他的水果,这时候用工厂方法的设计模式去做了这个事情,当用户用了一段时间之后,新的需求是要动态的创建香蕉了,这个时候你只需要再添加一个香蕉的类来,其他的都不用去修改了,你就完成了这个创建的工作,这样说不知你是否理解。
@Alex_QY1987说的就是很正确的
谢谢,那 看看 我上面的代码,添加一个香蕉,还要 添加一个香蕉的工厂,如果使用香蕉,Main方法还要改成香蕉的工厂来创建。
是否 真的是 不要修改?
@Qlin: 用反射的话,用配置文件就行可以了不用修改原来的代码,开闭原则,对扩展开放,对修改封闭!
@Qlin: 不要修改是说的,你不用去修改以前写好的算法。。。并不是说你不用修改MAIN函数的意思哦!比如你添加了一个香蕉工厂,再添加一个香蕉的算法,你不用去修改苹果和橘子工厂和算法。
还有Main函数是否需要修改,应该是取决业务需求,跟底层的工厂和算法,并没有太直接的联系呢!