简单工厂设计模式[]

Posted wangwangwangMax

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单工厂设计模式[]相关的知识,希望对你有一定的参考价值。

本宝宝只是一个菜鸟,写写学习笔记,以便温故知新,如果哪里不对或者不足,望大牛指正。

1.我们先举个例子说明一下,eg:加减乘除的运算[一步步优化]

 ⅰ.[第一种写法]

 class Program
    {
        static void Main(string[] args)
        {
            //第一种方法,显得不专业
            //输入
            Console.Write("请输入一个数字:");
            //接收
            string A = Console.ReadLine();
            Console.Write("请输入运算符,+、-、*、/");
            string B = Console.ReadLine();
            Console.Write("请输入第二个数字");
            string C = Console.ReadLine();
            Console.Write("结果等于");
            string D = "";
            if (B == "+")
            {
                //string转换为double,不能忘记tostring()
                D = (Convert.ToDouble(A)+Convert.ToDouble(C)).ToString();
            }
            if (B == "-")
            {
                D = (Convert.ToDouble(A) + Convert.ToDouble(C)).ToString();
            }
            if (B == "*")
            {
                D=(Convert.ToDouble(A)+Convert.ToDouble(C).ToString());
            }
            if (B == "/")
            {
                D=(Convert.ToDouble(A)+Convert.ToDouble(C).ToString());
            }
            Console.WriteLine("结果是:"+D);
        }
    }

 

  ⅱ.以上的这种写法,显得特别不专业,也不美观,那就优化一下,看看[第二种写法]

class Program
    {
        static void Main(string[] args)
        {
            //这是第二种方式
            try
            {
                Console.WriteLine("请输入一个数字");
                string sInum1 = Console.ReadLine();
                Console.WriteLine("请输入运算符,+、-、*、/");
                string Oper = Console.ReadLine();
                Console.WriteLine("请输入第二个数字");
                string sInum2 = Console.ReadLine();
                string sResult = "";
                switch (Oper)
                {
                    case "+":
                        sResult = (Convert.ToDouble(sInum1) + Convert.ToDouble(sInum2)).ToString();
                        break;
                    case "-":
                        sResult = (Convert.ToDouble(sInum1) + Convert.ToDouble(sInum2)).ToString();
                        break;
                    case "*":
                        sResult = (Convert.ToDouble(sInum1) + Convert.ToDouble(sInum2)).ToString();
                        break;
                    case "/":
                        if (sInum2 == "")
                        {
                            sResult = "被除数不能为0";
                        }
                        else
                        {
                            sResult = (Convert.ToDouble(sInum1) + Convert.ToDouble(sInum2).ToString());
                        }
                        break;
                }
                Console.WriteLine("结果为:" + sResult);
            }
            catch (Exception ex)
            {
               // Console.WriteLine(ex);
                Console.WriteLine("温馨提示,网站正在维修,请联系管理员");
            }   
        }
    }

 

  ⅲ.以上写法是不是也有许多不足呢?

    业务逻辑层和和客户端混合在一起,高耦合,关联性太强:1.不利于使用和扩展;2.不安全;

    那就再优化一下,看看[第三种写法][创建一个operating类之后调用]

    我们把业务逻辑层和客户端分开,就好比我们买个车子,只需知道它如何使用就好。

class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("请输入第一个数:");
                string sInum1 = Console.ReadLine();
                Console.WriteLine("请输入运算符,+、-、*、/");
                string sOper = Console.ReadLine();
                Console.WriteLine("请输入第二个数:");
                string sInum2 = Console.ReadLine();
                string sResult = "";
                sResult = (Operating.GetResult(Convert.ToDouble(sInum1),Convert.ToDouble(sInum2),sOper)).ToString();
                Console.WriteLine("结果为:"+sResult);
            }
            catch (Exception ex)
            {
                Console.WriteLine("温馨提示,网站正在维修,请联系管理员");
            }
        }
    }

 

    我们把业务逻辑层和客户端分开,以下代码相当于车子最核心,最底层的东西。

class Operating
    {
        public static double GetResult(double iNum1, double iNum2, string sOper)
        {
            double Result = 0d;
            switch (sOper)
            {
                case "+":
                    Result = iNum1 + iNum2;
                    break;
                case"-":
                    Result = iNum1 - iNum2;
                    break;
                case"*":
                    Result = iNum1 * iNum2;
                    break;
                case"/":
                    Result = iNum1 / iNum2;
                    break;
            }
            return Result;}
    }

 

  ⅳ.以上写法有什么不足呢?

    还是高耦合,如果在加一个开平方根,整个程序又要重新运行;

    假如现在是在做银行系统或安全系数高的,如果+,-,*,/都是各部分权限不同的人开发的,这样写它们都会互相看到;

    [那我们就试试第四种方式,简单工厂的设计模式]

    把Operating作为一个父类,写一些公共的东西,只是定义一个方法名,不作具体的实现操作。

class Operating
    {
        public double dNum1{get;set;}
        public double dNum2{get;set;}
        public virtual double GetResult()
        {
            double Result = 0;
            return Result;
        }
    }

    定义一个虚方法,子类只需覆写[+的操作]

class OperAdd:Operating
    {
        //子类覆写
        public override double GetResult()
        {
            double Result=0;
            Result = dNum1 + dNum2;
            return Result;
        }
    }
class OperReduce:Operating
    {
        public override double GetResult()
        {
            double Result = 0;
            Result = dNum1 - dNum2;
            return Result;
        }
    }
class OperRide:Operating
    {
        public override double GetResult()
        {
            double Result = 0;
            Result = dNum1 * dNum2;
            return Result;
        }
    }
class OperExcept:Operating
    {
        public override double GetResult()
        {
            double Result = 0;
            if (dNum2 == 0)
            {
                Console.WriteLine("被除数不能为0");
            }
            else
            {
                Result = dNum1 / dNum2;
            }
            return Result;
        }
    }

   定义一个工厂类OperateFactory.cs

class OperateFactory
    {
        //创建一个OperateFactory类,用于接收客户端传过来的是"+、-、*、/"
        public static Operating CreateOper(string sOper)
        {
            Operating oper = null;
            switch (sOper)
            {
                case"+":
                    oper = new OperAdd(); //如果是+,我们就创建一个+的对象,调用GetResult(),做处理
                    break;
                case"-":
                    oper = new OperReduce(); //如果是-,我们就创建一个-的对象
                    break;
                case"*":
                    oper = new OperRide();
                    break;
                case"/":
                    oper = new OperExcept();
                    break;
            }
            return oper;
        }
    }

    再看一下客户在调用的时候的代码:

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("请输入第一个数:");
            string sNum1 = Console.ReadLine();
            Console.WriteLine("请输入运算符,+、-、*、/");
            string sOper = Console.ReadLine();
            Console.WriteLine("请输入第二个数:");
            string sNum2 = Console.ReadLine();
            string sResult="";
            Operating oper;
            oper = OperateFactory.CreateOper(sOper);
            oper.dNum1 = Convert.ToDouble(sNum1);
            oper.dNum2 = Convert.ToDouble(sNum2);
            sResult = oper.GetResult().ToString();
            Console.WriteLine("结果等于:"+sResult);
        }
    }

   开发结果:

        

 

2.实例说明:

  简单工厂设计模式:在面向对象程序设计中,对程序开发人员而言,最常见的设计模式就是简单工厂模式。简单工厂模式根据提供给它的数据,返回几个类中的一个类的实例。通常返回的类都有一个公共父类和公共方法,但是每个方法实现的功能不同,并且根据不同的数据进行初始化。

  优点:工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品。简单工厂模式通过这种做法实现了对责任的分割。

低耦合,代码复用性高,扩展性强;

  缺点:当产品有复杂的多层等级结构时,工厂类只有自己,以不变应万变,就是模式的缺点。因为工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。同时,系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,有可能造成工厂逻辑过于复杂。

  

3.简单工厂角色与结构图:

  

  就暂时更新到这里吧,睡觉吧,毕竟身体棒棒才能继续学习。

以上是关于简单工厂设计模式[]的主要内容,如果未能解决你的问题,请参考以下文章

设计模式学习——简单工厂模式工厂模式抽象工厂模式

设计模式学习——简单工厂模式工厂模式抽象工厂模式

设计模式-简单工厂工厂方法模式抽象工厂模式详解

Delphi 设计模式:《HeadFirst设计模式》Delphi7代码---工厂模式之简单工厂

设计模式之简单工厂模式

C#之三十八 简单工厂设计模式