为什么要用简单工厂模式
作为对简单工厂模式的学习,首先要知道为什么要用简单工厂。
作为创建型设计模式,简单工厂模式的目的就是为了创建实例。提到创建实例,这里介绍一下c#的几种创建对象的方法。
1.通过new关键字进行实现。(最基本)
2.通过反射机制实现。
3.通过克隆方式实现。
4.通过工厂方式进行实现。
通常我们选用的是第一种创建方式,通过new关键字进行实例创建,这样就会将对象的创建和使用结合,大大提高了代码的耦合度,使得代码更难于修改和扩展。这时就要用到了第四种创建对象的方法——通过工厂方式进行实现,将创建于使用分离,让客户端无需知道对象是如何创建的。
创建对象
首先咱们抛开设计模式。
我们现在的需求就是需要实例一些需求的东西,比如说我想要一个辣椒的实例。
给出一个辣椒类Chili:
class Chili
{
public Chili()
{
//创建成功
Console.WriteLine("I Get a Chili");
}
public void BeEaten()
{
//被吃
}
}
好了现在我们需要一个辣椒。
class Program
{
public Chili chili;
public void Mian()
{
chili=new Chili();
chili.BeEaten();
}
}
现在需求改变了,我不想吃辣椒了,改成吃香菜了。
只能该你的Program类内的代码。
class Program
{
//就应该改成香菜类
public Coriander coriander;
public void Mian()
{
coriander=new Coriander();
Coriander.BeEaten();
}
}
也行,不算麻烦,毕竟就改了一次。
但是这时候项目又变了,让你又改回辣椒。这次你就要发现问题所在了:需求是一直在变的,也就是你实现的功能是要动态实现的。这时就要想到依赖倒置原则,要针对接口编程,不要针对实现编程。
这时提供一个蔬菜接口。
interface Vegetables
{
void EatIt();
}
只要是蔬菜就实现蔬菜接口
class Chili:Vegetables
{
public Chili()
{
//得到一个辣椒
}
public void EatIt()
{
//辣椒被吃
}
}
class Coriander:Vegetables
{
public Coriander()
{
//得到一把香菜
}
public void EatIt()
{
//香菜被吃
}
}
这时候你的Program就会变得有那么一点点的厉害。
class Program
{
//改成蔬菜类
public Vegetables vegetables;
public void Mian()
{
//这时只需要修改new后面的对象就可以了
vegetables=new Coriander();
vegetable.BeEaten();
}
}
现在你终于不用被变化的需求类的半死了,但是,开闭原则你考虑了吗。
哦豁,这个时候你要是想改成Vegetable的子类必然要修改Program类,而修改了Vegatable子类中的方法还是要修改Program类,也就是这段代码的问题出在了创建实例与使用实例写在同一个类内了,耦合度贼高,开闭原则成了自闭原则。
为了解决问题,我们就需要将实例对象单独拿出来,整一个工厂,单独进行实例。
正题开始
经历了上面漫长的过程后,终于等到了我们的简单工厂。简单工厂,顾名思义就是声明一个类通过静态方法的返回值类型来控制实例的生成。
还是拿辣椒和香菜举例,创建一个蔬菜工厂。
class Factory_Vegetables
{
public static Vegetables Creat(string what)
{
//这里可以用if判断也可用switch查找,为了省事我就写伪代码了
//辣椒
if Chili
return new Chili();
//香菜
else if Coriander
return new Coriander();
else
return null;
}
}
这时的Program类
class Program
{
public Vegetables vegetables;
public void Mian()
{
vegetables=Factory_Vegetables.Creat("Chili");//修改字符串来改变实例内容。
vegetable.BeEaten();
}
}
写到这里你就会发现,如果蔬菜子类的构造函数改变或者要增加或删除子类,这时只要维护修改工厂类即可,不会影响Program类;如果蔬菜接口发生了添加或移除方法的改变,只要修改Program,不会影响工厂类。这就是简单工厂。
疑问
关于开闭原则:是的没错,简单工厂只是调整了代码的耦合度,没有解决开闭原则的问题(可以用读取配置文件的形式创建实例,但是在产品子类更改后还是要改工厂,所以还是没有解决开闭原则),这就是为什么称之为简单工厂了,关于开闭原则将会在工厂模式中彻底解决。
优点
就一点,理解起来相对轻松。
因为不是GoF的23种设计模式中的亲儿子(后来加上的,亲儿子是工厂模式),所以我感觉除了理解起来较为轻松外没有任何优点。
缺点
首先,开闭原则的不完善就是最大的缺点。
其次,耦合度的问题,虽然Program实例与使用分离降低了耦合度,但是要注意一点,耦合这种东西在相同的代码量上是不可能消失的,只会转移,就像是代码中的能量守恒,那Program中的耦合度转到哪了呢。工厂类,工厂类做为所有创建所有实例的类自然是聚集了所有实例的耦合,就我经验而谈,低耦合的含义更多的体现在要看什么和什么耦合,就像是简单工厂,让实例和使用耦合分离就可以了。工厂模式种会对耦合度进行更深入的比较。
其次就是开闭原则完全没被遵守,无论如何都要修改源代码。