C#设计模式四(工厂方法模式)

C#设计模式之工厂方法模式

一、引言

在前面我们介绍到关于简单工厂设计模式的一些讲解。那么本篇章主要讲解工厂方法模式。但从字面上来看,简单工厂模式和工厂模式都是基于工厂思想的。那么两者之间自然存在着一定的相似。

先来回顾一下简单工厂模式的原理:
在这里插入图片描述

由上图可知,简单工厂模式中,
其中共有七个(或更多)的产品,这些产品符合一定的标准规范,及所有产品都是继承同一个类。
这样可以使所有产品具有同一类型的模板。实现基本类似的功能。
工厂类Operate中有一个switch语句,这个选择语句可以根据用户的指定来实例化7个(或更多)产品中的一个。其余没有选择的产品不会实例化,防止资源浪费。

所以简单工厂模式的核心就是选择性实例化对象。如下:

public class OperationFactory
{
    public static Operation createOperate(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;
                }
            case "sqr":
                {
                    oper = new OperationSqr();  //返回产品(平方类的对象)
                    break;
                }
            case "sqrt":
                {
                    oper = new OperationSqrt();  //返回产品(开方类的对象)
                    break;
                }
            case "+/-":
                {
                    oper = new OperationReverse();//返回产品(相反数类的对象)
                    break;
                }
        }

        return oper;  //将最终选择的返回
    }
}

那么工厂方法类和简单工厂类又什么区别呢?下面我们正式介绍

二、工厂方法模式和简单工厂模式不同

工厂方法模式将简单工厂模式中的switch语句中的分支全部变成了工厂子类,让其新建产品放到具体工厂子类中去。这个概念有点像是,将不同的产品放到不同的子工厂里去生成。然后通过选择哪个子工厂即选择了相应的产品了。例如一个家电工厂分为洗衣机工厂分部、冰箱工厂分部、热水器工厂分部。那么用户在选择热水器的话,就必须指定热水器工厂分部,让其进行热水器的生产。这样做能够将责任细化。而简单工厂模式中,因为只有一个工厂,所以无论什么产品都在同一个工厂中生产。所以工厂方法模式比简单工厂模式更加的细化,大大降低了耦合程度。

三、工厂方法模式的实现

与简单工厂模式相比,工厂方法模式主要不同点在于工厂中的选择部分。

//产品接口类

public 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
{
    public override double GetResult()
    {
        double result = 0;
        result = NumberA - NumberB;
        return result;
    }
}
class OperationMul : Operation
{
    public override double GetResult()
    {
        double result = 0;
        result = NumberA * NumberB;
        return result;
    }
}
class OperationDiv : Operation
{
    public override double GetResult()
    {
        double result = 0;
        if (NumberB == 0)
            throw new Exception("除数不能为0。");
        result = NumberA / NumberB;
        return result;
    }
}
class OperationSqr : Operation
{
    public override double GetResult()
    {
        double result = 0;
        result = NumberB * NumberB;
        return result;
    }
}
class OperationSqrt : Operation
{
    public override double GetResult()
    {
        double result = 0;
        if (NumberB < 0)
            throw new Exception("负数不能开平方根。");
        result = Math.Sqrt(NumberB);
        return result;
    }
}
class OperationReverse : Operation
{
    public override double GetResult()
    {
        double result = 0;
        result = -NumberB;
        return result;
    }
}

//工厂接口类,工厂规范

/// <summary>
/// 工厂标准规范/"接口",所有的子工厂必须继承它以便统一规范
/// </summary>
public abstract class Factory   
{
    public abstract Operation CreateOperation();
}

//具体子工厂类

public class FactoryAdd:Factory
{
    public override Operation CreateOperation()
    {
        return new OperationAdd();
    }

}
public class FactorySub : Factory
{
    public override Operation CreateOperation()
    {
        return new OperationSub();
    }

}
public class FactoryMul : Factory
{
    public override Operation CreateOperation()
    {
        return new OperationMul();
    }

}
public class FactoryDiv : Factory
{
    public override Operation CreateOperation()
    {
        return new OperationDiv();
    }

}
public class FactorySqr : Factory
{
    public override Operation CreateOperation()
    {
        return new OperationSqr();
    }

}
public class FactorySqrt : Factory
{
    public override Operation CreateOperation()
    {
        return new OperationSqrt();
    }

}
public class FactoryReverse : Factory
{
    public override Operation CreateOperation()
    {
        return new OperationReverse();
    }

}

//用户端

/*简单工厂的特点:
* 只有一个工厂
* 一个工厂只生产一种产品       
*/
/*工厂方法的特点
* 有多个子工厂
* 每个工厂各司其职,只生产属于自己的产品
* 将不同的产品划分,有较低的耦合度 
*/
static void Main(string[] args)
{
try
{
    Console.Write("请输入数字A:");
    string strNumberA = Console.ReadLine();
    Console.Write("请选择运算符号(+、-、*、/):");
    string strOperate = Console.ReadLine();
    Console.Write("请输入数字B:");
    string strNumberB = Console.ReadLine();
    string strResult = "";
    
    Factory fac = null;
    switch (strOperate)   //通过选择分支选择具体的子工厂
    {
        case "+":
                fac = new FactoryAdd();  //返回产品
                break;
        case "-":
                fac = new FactorySub();  //返回产品
                break;
        case "*":
                fac = new FactoryMul();  //返回产品
                break;
        case "/":
                fac = new FactoryDiv();  //返回产品
                break;
        case "sqr":
                fac = new FactorySqr();  //返回产品
                break;
        case "sqrt":
                fac = new FactorySqrt();  //返回产品
                break;
        case "+/-":
                fac = new FactoryReverse();//返回产品
                break;
    }
    Operation oper=fac.CreateOperation();              //调用子工厂的方法来进行创建产品类
    oper.NumberA = Convert.ToDouble(strNumberA);       //将选好的类的数值A赋值
    oper.NumberB = Convert.ToDouble(strNumberB);       //将选好的类的数值B赋值
    strResult = oper.GetResult().ToString();           //访问选好类中的方法返回操作结果
    Console.WriteLine("结果是:" + strResult);
    Console.ReadLine();
}
catch (Exception ex)
{
    Console.WriteLine("您的输入有错:" + ex.Message);
}

四、总结

综上所述,工厂方法模式与简单工厂模式之间的区别就是。工厂方法模式中存在着多个子工厂,由子工厂生产具体的产品。每个工厂各司其职,不混淆,耦合性地。方便扩展。

工厂方法模式的内部关系为:

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章