设计模式(九)之工厂模式

这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战算法

工厂模式:定义一个用于建立对象的接口,让子类来决定实例化哪个类,工厂方法使一个类的实例化延迟到子类。小程序

以前咱们看过简单工厂类,使用的是计算器做为例子。代码以下:markdown

简单工厂类Factory.cside

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
  /// 简单工厂类
namespace simpleFactory
{
    public class Factory
    {
        public static Ireckon CreateTreckon(string signStr)
        {
            Ireckon reckon = null;
   
            switch (signStr)
            {
                case "+":
                    reckon = new Plus();
                    break;
                case "-":
                    reckon = new Cut();
                    break;
                case "*":
                    reckon = new Ride();
                    break;
                default:
                    Console.WriteLine("暂不支持您输入的运算符");
                    break;
            }
            return reckon;
        }
   
    }
}
复制代码

下面咱们使用工厂模式来实现这个例子:oop

先构建一个工厂接口。post

而后加减乘除各建一个具体的工厂去实现这个接口。ui

定义一个算法接口,一个工厂接口,算法类继承算法接口,算法工厂类继承工厂接口(每一个算法类都须要有个算法工厂类来对应),将区分运算符号的逻辑部分放到客户端。咱们再增长算法的时候,只须要增长对应的算法类。算法工厂类,及修改客户端便可,这样不违反开放封闭原则。spa

代码以下:code

算法类:Ireckon.csorm

namespace simpleFactory
{
    public interface Ireckon
    {
        double getResult(double strNumberA, double strNumberB);
    }
}
复制代码

工厂类:IForecty.cs

namespace simpleFactory
{
    public interface IForecty
    {
        /// <summary>
        /// 工厂类:返回计算方法
        /// </summary>
        Ireckon CreateReckon();
    }
}
复制代码

减法类:Cut.cs

namespace simpleFactory
{
    public class Cut:Ireckon
    {
        public double result;
        public double getResult(double strNumberA, double strNumberB)
        {
            result = strNumberA - strNumberB;
            return result;
        }
    }
}
 
复制代码

减法工厂类:CutFactory.cs

namespace simpleFactory
{
    public class CutFactory:IForecty
    {
        public Ireckon CreateReckon()
        {
            return new Cut();
        }
    }
}
复制代码

加法类:Plus.cs

namespace simpleFactory
{
    public class Plus:Ireckon
    {
        public double result;
        public double getResult(double strNumberA, double strNumberB)
        {
            result = strNumberA + strNumberB;
            return result;
        }
    }
}
复制代码

加法工厂类:PlusFactory.cs

namespace simpleFactory
{
    public class PlusFactory:IForecty
    {
        public Ireckon CreateReckon()
        {
            return new Plus();
        }
    }
}
 
复制代码

乘法类:Ride.cs

namespace simpleFactory
{
    public class Ride:Ireckon
    {
        public double result;
        public double getResult(double strNumberA, double strNumberB)
        {
            result = strNumberA * strNumberB;
            return result;
        }
    }
}
复制代码

乘法工厂类:RideFactory.cs

namespace simpleFactory
{
    public class RideFactory:IForecty
    {
        public Ireckon CreateReckon()
        {
            return new Ride();
        }
    }
}
复制代码

客户端:Program.cs

namespace simpleFactory
{
    class Program
    {
        static void Main(string[] args)
        {
            // 数字A
            double strNumberA;
            // 数字B
            double strNumberB;
            // 运算符
            string signStr;
            // 运算结果
            double result;
            try
            {
                Console.WriteLine("请输入第一个数字");
                strNumberA = Convert.ToDouble(Console.ReadLine());
                Console.WriteLine("请输入运算符号");
                signStr = Console.ReadLine();
                Console.WriteLine("请输入第二个数字");
                strNumberB = Convert.ToDouble(Console.ReadLine());
                // 使用简单工厂类返回实例化子类的对象(由于子类中都是重写基类中的方法,指定类型的时候,直接声明基类就能够)
                //Ireckon reckon = Factory.CreateTreckon(signStr);
                //// 调用
                //result = reckon.getResult(strNumberA, strNumberB);
  
                // 工厂模式实现调用,如今咱们再增长算法的时候,只须要增长对应的算法类
                // 算法工厂类,及修改调用部分便可,这样不违反开放封闭原则。
                IForecty reckon = null;
                switch (signStr)
                {
                    case "+":
                        reckon = new PlusFactory();
                        break;
                    case "-":
                        reckon = new CutFactory();
                        break;
                    case "*":
                        reckon = new RideFactory();
                        break;
                    default:
                        Console.WriteLine("暂不支持您输入的运算符");
                        break;
                }
  
                result = reckon.CreateReckon().getResult(strNumberA, strNumberB);
                Console.WriteLine("运算结果为:" + result);
            }
            catch (Exception qq )
            {
                // 输出错误信息
                Console.WriteLine(qq.Message);
            }
            Console.ReadLine();
        }
    }
}
复制代码

上边的代码就使用工厂模式实现了简单工厂模式中的例子,代码看起来比简单工厂模式要复杂的多。可是,其更加合理。

简单工厂模式的优势:咱们能够对建立的对象进行一些 “加工” ,并且客户端并不知道,由于工厂隐藏了这些细节。若是,没有工厂的话,那咱们是否是就得本身在客户端上写这些代码,这就比如原本能够在工厂里生产的东西,拿来本身手工制做,不只麻烦之后还很差维护。

可是缺点也很明显:若是须要在方法里写不少与对象建立有关的业务代码,并且须要的建立的对象还很多的话,咱们要在这个简单工厂类里编写不少个方法,每一个方法里都得写不少相应的业务代码,而每次增长子类或者删除子类对象的建立都须要打开这简单工厂类来进行修改。这会致使这个简单工厂类很庞大臃肿、耦合性高,并且增长、删除某个子类对象的建立都须要打开简单工厂类来进行修改代码也违反了开-闭原则。

工厂模式是对简单工厂模式进一步的解耦,由于在工厂方法模式中是一个子类对应一个工厂类,而这些工厂类都实现于一个抽象接口。这至关因而把本来会由于业务代码而庞大的简单工厂类,拆分红了一个个的工厂类,这样代码就不会都耦合在同一个类里了。

工厂模式中,要增长产品类时也要相应地增长工厂类,客户端的代码也增长了很多。工厂方法把简单工厂的内部逻辑判断转移到了客户端代码来进行。

你想要加功能,原本是改工厂类的,而如今是修改客户端。并且各个不一样功能的实例对象的建立代码,也没有耦合在同一个工厂类里,这也是工厂方法模式对简单工厂模式解耦的一个体现。工厂方法模式克服了简单工厂会违背开-闭原则的缺点,又保持了封装对象建立过程的优势。

但工厂方法模式的缺点是每增长一个产品类,就须要增长一个对应的工厂类,增长了额外的开发量。

有好的建议,请在下方输入你的评论。 欢迎访问我的博客 guanchao.site

欢迎访问小程序:

在这里插入图片描述

相关文章
相关标签/搜索