首页 > 代码库 > 设计模式------工厂方法模式

设计模式------工厂方法模式

工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类.

角色:

1.抽象工厂(Creator)角色:

是工厂方法模式的核心,与应用程序无关。任何在模式中创建对象的工厂类必须实现这个接口。


2.具体工厂(ConcreteCreator)角色:

这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。


3.抽象产品(Product)角色:

工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。


4.具体产品(ConcreteProduct)角色:

这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。


结构图:



适用情况:

1.对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。

2.只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程对于使用者来说是透明的。


工厂方法模式VS简单工厂模式:

 下面以编写“计算器”的小程序为例,对比学习工厂方法模式。


1.简单工厂模式:


简单工厂类:


工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类。对于客户端来说,去除了与具体产品的依赖。当增加其他算法时,需要在工厂类中加case分支条件,这样就违背了“开放-封闭原则”。

简单工厂模式链接


2.工厂方法模式:


 
工厂方法模式对简单工厂模式进行了抽象,将简单工厂的内部逻辑判断移到了客户端中。它有一个抽象的Factory类(可以是抽象类和接口),这个类将不再负责具体的产品生产,只制定一些规范,具体的生产工作由其子类去完成。


工厂方法模式实现:

运算类:

class Operation
    {
        private double _numberA = 0;
        private double _numberB = 0;

        public double NumberA
        {
            get { return _numberA; }
            set { _numberA = value; }
        }

        public double NumberB
        {
            get { return _numberB; }
            set { _numberB = value; }
        }

        /// 得到运算结果        
        
        public virtual double GetResult()
        {
            double result = 0;
            return result;
        }
    }

加法类:

 class OperationAdd : Operation
    {
        public override double GetResult()
        {
            double result = 0;
            result = NumberA + NumberB;
            return result;
        }
    }

减法类:

class OperationSub : Operation
    {
       ...
    }

乘法类:

 class OperationMul : Operation
    {
        ...
    }

除法类:

 class OperationDiv : Operation
    {
        public override double GetResult()
        {
            double result = 0;
            if (NumberB == 0)
                throw new Exception("除数不能为0。");
            result = NumberA / NumberB;
            return result;
        }
    }

根据依赖倒转原则,把工厂类抽象出一个接口,这个接口具有一个创建抽象产品的工厂方法,所有生产具体类的工厂,都要实现这个接口。

工厂类

 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.NumberA = 1;
            oper.NumberB = 2;
            double result=oper.GetResult();

            Console.WriteLine(result);

            Console.Read();
        }

最后在控制台窗口显示得数“3”。


分析:

核心工厂类不再负责产品的创建,成为一个抽象工厂角色,使一个类的实例化延迟到其子类,这样进一步抽象化使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。当增加新的算法时,不需更改原有的工厂类,只需增加此功能的运算类和相应的具体生产工厂,只对扩展开放,对修改关闭,弥补了简单工厂的不足,仍保持封装对象创建过程的优点,降低了客户程序与产品对象的耦合。工厂方法的缺点就是每增加一个产品,需要增加这个产品工厂的类,利用反射技术可以进行完善。


小编寄语:通过写博客,加深了理解,沉淀了知识。欢迎大家指点,我们共同进步。