说说设计模式~工厂方法模式(Factory Method)
在简单工厂的讲解中,出现了很多问题,我们对象统一行为抽象出一个接口(或者抽象类)之后,再根据你传入的类型进行创建实例,这只适合于你有固定行为的场合,当你要实现接口的类型处于不定数时,则不适合使用简单工厂模式,而应该用工厂方法了。
适用场合:
子类有统一的操作行为
子类的数量不固定,随时可能有新的功能子类出现
工厂方法优势:
子类与子类是并列的,关系不精密,程序耦合度比较大
完全符合OCP原则,对代码的修改关闭,对代码的扩展开放
创建具体对象方法灵活,可以使用反射或者第三方IOC容器
工厂方法模式代码片断,主要从简单工厂中修改过来的,下面是结果图
1 统一操作行为,主要将统一接口抽象出来,让具体子类去实现它
1 /// <summary> 2 /// 工厂方法的规定操作行为 3 /// </summary> 4 public interface ICreate 5 { 6 void Create(); 7 }
如果它的一部分功能对于子类是公用的,相同的,那我们需要将ICreate设计成抽象类abstract class ,代码可以是这样
1 public abstract class CreateBase 2 { 3 /// <summary> 4 /// 每个子类都公用的属性或者方法 5 /// </summary> 6 protected string CreateName 7 { 8 get 9 { 10 return "一个工厂方法模式"; 11 } 12 } 13 /// <summary> 14 /// 子类必须去实现的抽象方法行为 15 /// </summary> 16 abstract void Create(); 17 }
而一个建立抽象行为的工厂,它可以被其它具体行为工厂继承,它提供一个方法,叫子类工厂去实现它,并返回子类对象本身。同样,根据业务需求,可以由抽象类实现
1 /// <summary> 2 /// 抽象工厂规定行为 3 /// </summary> 4 public interface CreateFactory 5 { 6 ICreate CreateObject(); 7 }
对于具体对象而言,它们要做的就是去实现抽象的行为,以下是一个人物类,它去实现Create方法。
1 /// <summary> 2 /// 具体对象实现 3 /// </summary> 4 public class People : ICreate 5 { 6 7 #region ICreate 成员 8 9 public void Create() 10 { 11 Console.WriteLine("创建人类"); 12 } 13 14 #endregion 15 }
而对于具体工厂来说,主要作用是去创建一个具体对象的实例,代码如下:
1 /// <summary> 2 /// 具体工厂进行生产对象 3 /// </summary> 4 public class PeopleFactory : CreateFactory 5 { 6 #region CreateFactory 成员 7 8 public ICreate CreateObject() 9 { 10 return new People(); 11 } 12 13 #endregion 14 }
以程序调用时,我们需要先去创建一个工厂,然后再使用工厂中的方法,来完成我们的操作
1 FactoryMethod.CreateFactory createFactory = new FactoryMethod.PeopleFactory(); 2 FactoryMethod.ICreate iCreate = createFactory.CreateObject(); 3 iCreate.Create();
而这时,我们看到,代码有些不完美,那就是在创建具体工厂时还是出现了new,即还是存在着代码间的依赖,如何解除这样依赖使代码更加松耦合呢,这时,我们可以使用反射或者IOC
容器来解决这个问题:
1 string strfactoryName = ConfigurationManager.AppSettings["factoryName"]; 2 FactoryMethod.CreateFactory factory = (FactoryMethod.CreateFactory)Assembly.Load("FactoryMethod").CreateInstance("FactoryMethod." + strfactoryName); 3 FactoryMethod.ICreate create = factory.CreateObject(); 4 create.Create();
我们从代码中可以看到,具体工厂的创建已经被约束到了配置文件中,这是我们可以接受的,呵呵。
事实上,微软自己在它的组件中大大使用了工厂方法模式,如MVC中的Controller的创建方法,也是这个道理。