简介
我用最简洁而直接的方式来描述一下,什么是简单工厂模式。一句话就是,工厂类使用switch case语句返回特定类型。
下面,我们用一个脑补故事来描述一下。
假设有个女朋友
假设,仅仅是假设啊,你有一个女朋友(不是new出来的那种啊),而且,你的女朋友很喜欢小动物,但是这个女朋友有个问题,她第一天可能喜欢猫,就让你给她弄一只猫,第二天可能喜欢狗,就让你弄条旺财来,后天就不知道喜欢什么小动物了(就跟产品经理的需求一样,哈哈哈哈),毕竟女朋友都假设出来了,那我们还是需要好好地满足一下她这无理的需求吧。那么,我们就用代码来实现和满足一下女朋友的需求。
我们先来定义一下猫类和狗类。
public class Cat
{
public void Speak()
{
Console.WriteLine("喵喵喵");
}
}
public class Dog
{
public void Speak()
{
Console.WriteLine("汪汪汪");
}
}
好了,现在来到了第一天,女朋友说她想要一只猫,程序员嘛,想要什么对象不能通过new出来的?
class Program
{
static void Main(string[] args)
{
Cat cat = new Cat();
cat.Speak();
}
}
好了,我们通过new来满足了女朋友第一天的需求了。但第二天,女朋友想要条狗了,那我们的代码怎么办呢。
class Program
{
static void Main(string[] args)
{
Dog dog = new Dog();
dog.Speak();
}
}
嗯,就这样,改好了,现在可以满足女朋友想要狗的这个愿望了,但程序员有一个本质的特点,是什么呢?那就是懒咯,你看哦,这里从需要猫变成需要狗,代码基本上,就是擦掉重写,对于程序员来说,这不能忍啊,但是女朋友的需求又不能不满足,那该怎么办呢?这个时候,简单工厂模式,可以让你既能偷懒,又能满足你女朋友的一百种想法(让你死的方法)。下面我们来看看如何把这个案例改成使用简单工厂模式来实现。
public abstract class Animal
{
public abstract void Speak();
}
public class Cat : Animal
{
public override void Speak()
{
Console.WriteLine("喵喵喵");
}
}
public class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("汪汪汪");
}
}
public class Bird : Animal
{
public override void Speak()
{
Console.WriteLine("吱吱吱");
}
}
首先,因为猫、狗它们都属于动物,我们可以先写一个抽象类Animal,然后猫、狗继承Animal类,并实现Animal中的Speak()方法,有的人,可能就要问了,这还抽象了出来,不是更麻烦了吗,代码也变多了,稍安勿躁,接下来就是见证奇迹的时刻了。
首先我们需要来写一个工厂类,这个类里面有一个静态方法,参数为传入一个动物类型的字符串,根据类型,返回继承自Animal的子类型(这个是面向对象的特性)。
public class AnimalFactory
{
public static Animal CreateAnimal(string animalType)
{
switch (animalType)
{
case "cat":
return new Cat();
case "dog":
return new Dog();
case "bird":
return new Bird();
default:
throw new ArgumentException("未知动物类型");
}
}
}
那现在要满足女朋友的需求就很简单。
想要一只猫,听她叫(是听猫叫,不是听女朋友叫啊)?简单。
class Program
{
static void Main(string[] args)
{
Animal animal = AnimalFactory.CreateAnimal("cat");
animal.Speak();
}
}
什么,又想要一只狗,也想听它叫?简单。
class Program
{
static void Main(string[] args)
{
Animal animal = AnimalFactory.CreateAnimal("dog");
animal.Speak();
}
}
哦?想换成一只鸟?简单。
class Program
{
static void Main(string[] args)
{
Animal animal = AnimalFactory.CreateAnimal("bird");
animal.Speak();
}
}
通过上面的代码,我们可以看到啊,需要什么动物,我们直接对工厂类静态方法传不同的字符串值就可以了,不需要像之前那样,要将所有代码都修改掉,而且,如果女朋友想要新的小动物,我们只需要在AnimalFactory的静态方法中添加相应的小动物类就可以了。
其实简单工厂模式是需要将一类事物抽象起来(对应这里的Animal类),然后返回对应抽象的实现(对应这里的Cat、Dog、Bird类),这样就可以做到解耦合(没有使用简单工厂之前,我们如果需要修改女朋友想要的动物类型,必须重新定义)。
好了,现在假设的女朋友哄好了,代码也学到了,是时候该醒醒啦。
总结
对于简单工厂来说,有个缺点,那就是它里面使用到的switch case,因为每增加一个Animal的子类,它也要相应地增加代码量,在数量比较少的时候还好,要是多的话,你就会看到一个很长很长很长很长的switc case 语句在那里,而且,一般看到swtich case,我都会思考优化掉它,这里其实可以用抽象工厂模式来解决,这就是下一篇博客需要写的内容啦。
在这里,我还想说说我自己对于设计模式存在的意义的一些看法。对于我个人理解而言,其实设计模式的根本目的,就是让代码尽可能地减少耦合,一个少耦合的系统,是更适合于拓展和更新的,这样的系统在面对需求或者变更时,程序员才不会那么的累。另外,其实大部分的设计模式透露出来的思想都是依赖抽象而不是依赖于实现(比如使用接口或者抽象类)。