一、什么是工厂模式
给一个创建对象的接口,让其子类决定创建哪个具体对象.
允许接口创建对象,但使用哪个类来创建对象,则是交由子类决定的。工厂模式像是一个工厂群,工厂A生产A产品,工厂B生产B产品,你有什么东西要生产,我就有什么工厂负责给你生产.
UML图
二、适用场景
多同基类的子类需要生成,比如怪物工厂,野怪A 野怪B等等,他们可以建立一套怪物的对象 类,然后有对应的工厂和具体工厂.在工厂里面怪物已经定义好了,外界只需要调用工厂类创建即可,不用关心对象具体是怎么创建的.
三、优缺点
优点
解决了简单工厂的不符合封闭原则的情况
实现解耦合,将创建和使用分开
将创建对象封装,减少代码重复度.
缺点
若要增加对象,则要增加对应的工厂类.
创建哪一个对象的逻辑交给了客户端.
四、大话中的例子
雷锋工厂的例子,学雷锋的有大学生/有雷锋社区, 工厂类就需要对应的大学生工厂/雷锋社区工厂,你要大学生去做好事还是雷锋社区去做好事,声明实例一个对应的工厂就好,这个工厂可以创建你要的.
五、我的例子
using System;
namespace FactoryMode
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("=========与飞段角都的战斗==========");
CreateNinja shikamaruFact = new CreateShikamaru();//需要客户端确定生产哪个对象
KonohaNinja shikamaru = shikamaruFact.CreateObject();
Console.WriteLine("=========第一回合==========");
shikamaru.UseKunai();
shikamaru.ExclusiveSkill();
CreateNinja narutoFact = new CreateNaruto();
KonohaNinja naruto = narutoFact.CreateObject();
Console.WriteLine("=========第二回合==========");
naruto.UseKunai();
naruto.ExclusiveSkill();
Console.ReadKey();
}
}
public abstract class KonohaNinja
{
protected string name;
public KonohaNinja(string name)
{
this.name = name;
}
public void UseKunai()
{
Console.WriteLine("{0}使用了苦无", name);
}
public abstract void ExclusiveSkill();
}
public class Shikamaru : KonohaNinja
{
public Shikamaru(string name) : base(name)
{
}
public override void ExclusiveSkill()
{
Console.WriteLine("{0}使用了影子绞首术", name);
}
}
public class Naruto : KonohaNinja
{
public Naruto(string name) : base(name)
{
}
public override void ExclusiveSkill()
{
Console.WriteLine("{0}使用了风遁螺旋丸手里剑", name);
}
}
public class Kakashi : KonohaNinja
{
public Kakashi(string name) : base(name)
{
}
public override void ExclusiveSkill()
{
Console.WriteLine("{0}使用了雷切", name);
}
}
public interface CreateNinja
{
KonohaNinja CreateObject();
}
public class CreateShikamaru : CreateNinja
{
public KonohaNinja CreateObject()
{
return new Shikamaru("奈良鹿丸");
}
}
public class CreateNaruto : CreateNinja
{
public KonohaNinja CreateObject()
{
return new Naruto("漩涡鸣人");
}
}
public class CreateKakashi : CreateNinja
{
public KonohaNinja CreateObject()
{
return new Kakashi("卡卡西");
}
}
}
运行结果
如果想把第二回合的人物换成卡卡西出场,只需要将 CreateNinja narutoFact = new CreateNaruto();
换成 CreateNinja narutoFact = new CreateKakashi ();
即可.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("=========与飞段角都的战斗==========");
CreateNinja shikamaruFact = new CreateShikamaru();//需要客户端确定生产哪个对象
KonohaNinja shikamaru = shikamaruFact.CreateObject();
Console.WriteLine("=========第一回合==========");
shikamaru.UseKunai();
shikamaru.ExclusiveSkill();
CreateNinja narutoFact = new CreateKakashi();//这里替换了
KonohaNinja naruto = narutoFact.CreateObject();
Console.WriteLine("=========第二回合==========");
naruto.UseKunai();
naruto.ExclusiveSkill();
Console.ReadKey();
}
}
PS:这个例子并不是很贴切,但整体的构架思想是这样的,使用工厂模式我们创建的对象一般是可重复的,而不是独有的,可以将上述人物类进一步抽象,比如 近程忍者,远程忍者,医疗忍者等等, 这时候创建工厂,就不是只针对一个特定的忍者创建的工厂了,而是一个类型忍者的工厂.用工厂模式,从工作量来看并未减轻太多,可能还有增加,而且创建哪种对象的逻辑也迁移到了客户端,但工厂模式完备了开放封闭的原则,将 创建对象与使用对象解耦合.如果要增加对象只需要增加该对象,和对应的对象工厂,不影响其他的类使用.工厂模式去代替直接实例化对象是为了可复用,并且可以实现模块间的解耦。