工厂模式主要是为创建对象提供接口,以便将创建对象的具体过程屏蔽隔离起来提高灵活性。
工厂模式分三类:1、简单工厂模式(Simple Factory)
2、工厂方法模式(Factory Method)
3、抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性
一、简单工厂模式
简单工厂模式又称静态工厂方法模式,定义一个创建对象接口
1、类图
2、代码
public class Operation //运算类 { private double _numA = 0; private double _numB = 0; public double NumA { get { return _numA; } set { _numA = value; } } public double NumB { get { return _numB; } set { _numB = value; } } public virtual double GetResult() { double result = 0; return result; } class OperationAdd : Operation //加法 { public override double GetResult() { //return base.GetResult(); double result = 0; result = NumA + NumB; return result; } } class OperationSub : Operation //减法 { public override double GetResult() { double result = 0; result = NumA - NumB; return result; } } 乘法 除法略 public class OperationFactory { public static Operation creatoperate(string operate) { Operation oper = null; switch (operate) { case "+": oper = new OperationAdd(); break; case "-": oper = new OperationSub(); break; case "*": oper = new OperationMul(); break; case "/": oper = new OperationDiv(); break; } return oper; } } static void Main(string[] args) { Operation oper; oper = OperationFactory.creatoperate("+"); oper.NumA =1.1; oper.NumB =10; double result=oper.GetResult (); Console.WriteLine("结果是:"+result ); }
用工厂类来完成创建实例的过程,只要输入符号,工厂就实例化出合适的对象。
但是,用开放-封闭原则来分析,如果增加一种运算比如平方根,在工厂类中也要加相应的逻辑判断,显然违背了开闭原则,这时工厂方法模式应运而生。
二、工厂方法模式
去掉了简单工厂模式中的工厂方法的静态属性,使它可以被子类继承,这样集中在工厂类中的方法可以由工厂方法模式中的不同子类承担。
1、类图
2、代码
interface IFactory //抽象工厂 { Operation CreateOperation(); } class AddFactory : IFactory //加法工厂 { public Operation CreateOperation() { return new OperationAdd(); } } class SubFactory : IFactory //减法工厂 { public Operation CreateOperation() { return new OperationSub(); } } static void Main(string[] args) { IFactory OperFactory = new AddFactory(); Operation oper = OperFactory.CreateOperation(); oper.NumA = 1; oper.NumB = 2; double result = oper.GetResult(); Console.WriteLine(result ); }
相比简单工厂模式多了各个运算类的工厂。可以看出工厂方法的加入,使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。因为如果不能避免这种情况,可以考虑使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。
小结:工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口。那我们是否一定要在代码中遍布工厂呢?大可不必。也许在下面情况下你可以考虑使用工厂方法模式:
1) 当客户程序不需要知道要使用对象的创建过程。
2) 客户程序使用的对象存在变动的可能,或者根本就不知道使用哪一个具体的对象。
三、抽象工厂模式
提供了一个创建一系列相关或互相依赖的接口,而无须指定它们具体的类。
1、类图
2、代码
class User //用户类 { private int _id; public int ID { get {return _id ;} set {_id =value ;} } private string name; public string Name { get {return name ;} set {name=value ;} } } interface IUser //用户接口 { void Insert(User user); User GetUser(int id); } class sqlseverUser : IUser //访问sql的User { public void Insert(User user) { Console.WriteLine("在sql中给User表增加一条记录"); } public User GetUser(int id) { Console.WriteLine("在sql中根据ID得到User表中的一条记录"); return null; } } class accessUser : IUser //访问access的User { public void Insert(User user) { Console.WriteLine("在access中给User表添加一条记录"); } public User GetUser(int id) { Console.WriteLine("在access中根据ID得到User中的一条记录"); return null; } } interface IFactory //定义一个创建访问User表的抽象工厂接口 { IUser CreateUser(); } class sqlFactory : IFactory //实现Ifactory接口,实例化sqlserverUser { public IUser CreateUser() { return new sqlseverUser(); } } class accessFactory : IFactory { public IUser CreateUser() { return new accessUser(); } } class Program { static void Main(string[] args) { User user = new User(); IFactory factory = new sqlFactory(); IUser iu = factory.CreateUser(); iu.Insert(user); iu.GetUser(1); Console.Read(); } }
优点:1、便于交换产品系列,使得改变一个应用的具体工厂变得非常容易
2、让具体的创建实例过程与客户端分离,客户端通过它们的抽象接口操纵,产品的具体类名也被具体工厂的实现分离,不会再客户端代码中出现
缺点:增加项目时更改的类多,产生大批量改动