zoukankan      html  css  js  c++  java
  • 简单工厂模式

      手上有一个《大话设计模式》,之前已经看了一些了,但是没有认真做一做记录。这里是第一个最简单的设计模式:简单工厂模式

      工厂当然就是生产东西的,在程序设计中(面向对象的程序设计)这个工厂则是负责生产对象的。

    先看一个写一个控制台计算器的例子:要求实现一个控制台计算器,输入两个数和运算符号,然后得出结果。

    版本1:

    class Program
        {
            static void Main(string[] args)
            {
                try
                {
                    Console.WriteLine("输入A:");
                    int numA = Convert.ToInt32(Console.ReadLine());
                    Console.WriteLine("选择运算符(+ - * /):");
                    string strOperate = Console.ReadLine();
                    Console.WriteLine("输入B:");
                    int numB = Convert.ToInt32(Console.ReadLine());
                    string strResult = "";
                    switch (strOperate)
                    {
                        case "+":
                            strResult = (numA + numB).ToString();
                            break;
                        case "-":
                            strResult = (numA - numB).ToString();
                            break;
                        case "*":
                            strResult = (numA * numB).ToString();
                            break;
                        case "/":
                            if (numB!=0)
                            {
                                strResult = (numA / numB).ToString();
                            }
                            else
                            {
                                strResult = "除数不能为0!";
                            }
                            break;
                        default:
                            strResult = "非法操作符";
                            break;
                    }
    
                    Console.WriteLine("运算结果是:"+strResult);
                    Console.ReadLine();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("输入有错:"+ex.Message);
                }
            }
        }

    就运行来说完全没有问题,但是就这样真的没毛病吗?这是用计算机的思维在写程序,完全没有面向对象的思想,比如要把这个东西改成一个windows的计算器,或者web上,代码就不能用了。

    封装:

    将业务逻辑封装起来,和界面逻辑分开,把运算的部分封装成一个类。这样就让这个运算类在其它地方复用了。

    版本2:

    /// <summary>
        /// 运算类
        /// </summary>
        public class Operation
        {
            /// <summary>
            /// 获取计算结果
            /// </summary>
            /// <param name="numA">数字A</param>
            /// <param name="numB">数字B</param>
            /// <param name="strOperate">运算符</param>
            /// <returns></returns>
            public static double GetResult(double numA,double numB,string strOperate)
            {
                double result = 0d;
                switch (strOperate)
                {
                    case "+":
                        result = numA + numB;
                        break;
                    case "-":
                        result = numA - numB;
                        break;
                    case "*":
                        result = numA * numB;
                        break;
                    case "/":
                        if (numB != 0)
                        {
                            result = numA / numB;
                        }
                        else
                        {
                            throw new Exception("除数不能为0");
                        }
                        break;
                    default:
                        //strResult = "非法操作符";
                        throw new Exception("不支持的操作符");
                }
                return result;
            }
        }
    
    class Program
        {
            static void Main(string[] args)
            {
                try
                {
                    Console.WriteLine("输入A:");
                    double numA = Convert.ToDouble(Console.ReadLine());
                    Console.WriteLine("选择运算符(+ - * /):");
                    string strOperate = Console.ReadLine();
                    Console.WriteLine("输入B:");
                    double numB = Convert.ToDouble(Console.ReadLine());
                    double result = Operation.GetResult(numA,numB,strOperate);
                    Console.WriteLine("运算结果是:"+ result);
                    Console.ReadLine();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("输入有错:"+ex.Message);
                }
            }
        }

    面向对象的三大思想之一封装就在这里体现了。还有两大思想呢?

    再回头来看看这个计算器,逻辑和界面已经分离了,代码可以在其它地方复用了,还有什么问题呢?如果要增加一个运算呢,比如增加一个开根号运算sqrt需要怎么修改呢?

    最容易想到的是就是增加switch的分支吧,再增加一个分支支持开根号就行了这又存在一个问题了:明明只要增加一个开根号运算,但是其它运算规则都来参加编译。书上举了一个特别有意思的例子:如果一个公司系统让做薪资管理系统的维护,原来是 技术人员(月薪),销售(底薪+提成),经理(年薪+股份)三种计算薪水规则,现在要增加兼职人员(时薪)的算法,然后做维护,按照之前的写法,把运算的类拿出来维护,做修改,维护人员除了完成兼职算法以外再悄悄的在技术人员(月薪)地方加一行代码

    if(我)
    {
        salary = salary*1.1;
    }

    工资就比原来多了10%(违法要坐牢),所以这样是有风险的!所以这时候应该把各种运算进行分离,在分离的过程中就运用到了继承和多态。

    版本3:

    /// <summary>
        /// 运算基类
        /// </summary>
        public class Operation
        {
            public double numA { get; set; }
            public double numB { get; set; }
            public virtual double GetResult()
            {
                double result = 0;
                return result;
            }
        }
        /// <summary>
        /// 加法类
        /// </summary>
        class OperateAdd : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = numA + numB;
                return result;
            }
        }
        /// <summary>
        /// 减法类
        /// </summary>
        class OperateSub : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = numA - numB;
                return result;
            }
        }
        /// <summary>
        /// 乘法类
        /// </summary>
        class OperateMul : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = numA * numB;
                return result;
            }
        }
        /// <summary>
        /// 除法类
        /// </summary>
        class OperateDiv : Operation
        {
            public override double GetResult()
            {
                double result = 0;
                result = numA / numB;
                return result;
            }
        }

    现在是各种类已经有了,但是要怎么样才能得到不同的运算类呢?这里就需要一个工厂了,根据输入运算符得到对应的运算类。

    /// <summary>
        /// 运算类工厂
        /// </summary>
        public class OperationFactory
        {
            public static Operation CreateOperation(string operate)
            {
                Operation oper = null;
                switch (operate)
                {
                    case "+":
                        oper = new OperateAdd();
                        break;
                    case "-":
                        oper = new OperateSub();
                        break;
                    case "*":
                        oper = new OperateMul();
                        break;
                    case "/":
                        oper = new OperateDiv();
                        break;
                    default:
                        //strResult = "非法操作符";
                        throw new Exception("不支持的操作符");
                }
                return oper;
            }
        }
    class Program
        {
            static void Main(string[] args)
            {
                try
                {
                    Console.WriteLine("输入A:");
                    double numA = Convert.ToDouble(Console.ReadLine());
                    Console.WriteLine("选择运算符(+ - * /):");
                    string strOperate = Console.ReadLine();
                    Console.WriteLine("输入B:");
                    double numB = Convert.ToDouble(Console.ReadLine());
                    var oper = OperationFactory.CreateOperation(strOperate);
                    oper.numA = numA;
                    oper.numB = numB;
                    double result = oper.GetResult();
                    Console.WriteLine("运算结果是:"+ result.ToString());
                    Console.ReadLine();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("输入有错:"+ex.Message);
                }
            }
        }

    这就是简单工厂模式,如果要改界面,那就换界面就行了,如果要增加运算法则,那就增加类就行了,不过还要修改工厂增加switch分支,由工厂来复制创建类,代码复用性和可维护性大大地提高了。

    (排版混乱,以后慢慢改进)

  • 相关阅读:
    剑指offer python版 正则表达式匹配
    剑指offer python版 删除链表中重复的结点
    剑指offer python版 在O(1)时间删除链表结点
    剑指offer python版 打印1到最大的n位数
    剑指offer python版 数值的整数次方
    剑指offer python版 二进制中1的个数
    剑指offer python版 剪绳子
    剑指offer python版 机器人的运动范围
    设计模式(二) 工厂模式
    设计模式(一) 单例模式
  • 原文地址:https://www.cnblogs.com/Iamsorry/p/6381443.html
Copyright © 2011-2022 走看看