一句话概括:工厂模式是为了将“产品”而不是将“工厂”与应用程序解耦。所以适合用在“产品”变化较多的地方,用来封装“产品”的变化。
按照很多文章的套路, 我们还是用一个故事作为切入:话说一个老和尚有三个徒弟,老大善于扫地,老二善于砍柴,老三善于浇花。于是每天老和尚要做的就是当他想扫地的时候,就叫来老大,然后说“老大,扫地去”。想砍柴时候就叫来老二,说:“老二,砍柴去!”。。。。。
以上就是我们通常不应用设计模式的解决办法。
怎奈随着老和尚年龄增长,开始记不住几个徒弟的优势了,于是怎么办呢,找一个年轻的小和尚替他管理吧。于是老和尚只要记得想干什么就行了,比如说想扫地的话只要告诉小和尚说:“扫地”。小和尚就会叫来老大,然后老和尚下令“干活”就ok啦!(不过下面的故事会让大家看出来,简单工厂方法随着产品种类的增多会违背开闭原则)
这个就是通常我们应用的简单工厂方法。这种模式将创造产品的所有工厂集中成一个工厂,就是这里的小和尚,而老和尚就是应用程序。对老和尚来说只要命令干活就行了,具体是谁在干活并不用记住。
不过以上也存在问题,就是当工种增加后,小和尚需要记忆更多的东西。
class 大徒弟:徒弟
{
public void 干活()
{
扫地
}
}
class 二徒弟:徒弟
{
public void 干活(){浇花}
}
class 小和尚
{
public 徒弟 找来对应的徒弟(string 活的名称)
{
switch(活的名称)
{
case "浇花":
return "大徒弟";
break;
......
}
}
}
Main()
{
小和尚 a = new 小和尚();
徒弟 b = a.找来对应的徒弟("浇花");
b.干活();
}
如果需要的工种多了,势必要增加小和尚类里的 case, 那么就违反了开闭原则。而且当内容或者业务逻辑多了,这个类也不好维护。
所以,我们的工厂方法诞生了。。。。。
他给每个徒弟配备一个助理,每个助理负责叫来各自的徒弟,于是我们的应用程序便成了这样子
class 助理{
徒弟 叫来徒弟()
{
}
}
class 大徒弟助理:助理
{
徒弟 叫来徒弟(){ return 大徒弟;}
}
Main()
{
助理 a = new 大徒弟助理();
徒弟 b = a.叫来徒弟();
b.干活();
}
这样子就是我们的工厂方法,各个主力就是各个具体工厂,助理抽象类就是工厂。