C# 丢弃工厂模式,反射方式实现计算器

原创 2017年09月04日 15:13:11
在学习设计模式的时候,其中有一种模式叫工厂模式,工厂模式里经典的案例就是设计一个计算器,在工厂模式里都是用swith() ... case ...来实例化类。并调用类里的方法
例:
switch (symbol)
            {
                case "+":
                    bc = new Add();
                    bc.Calculation(num1,num2);
                    break;
                case "-":
                     bc = new Sub();
                    bc.Calculation(num1, num2);
                    break;
                case "*":
                    bc = new Mul();
                    bc.Calculation(num1, num2);
                    break;
                case "/":
                    bc = new Div();
                    bc.Calculation(num1, num2);
                    break;
                default:
                    bc = new BaseClass();
                    bc.Calculation(num1, num2);
                    break;
            }

每添加一种计算方法,那就要在swith() ... case ...里实例化该类,这样有一个步骤忘了,就计算不出来结果

所以我就想要是只要类的名字,然后通过这个名字实例化类出来,然后再调用类里计算的方法,
这样的话,我就只需要编写类的计算方法,然后把这个类的类名告诉程序,程序在计算时,通过
用户输入的计算符号(如+,-,*,/,√)来进行选择用那个类进行计算,有了这个思路,但是这种方
法是否可行呢,有了反射,这个想法是肯定可以的,下面就是我用这种方式实的!

定义一个基类BaseClass,里面包含了计算的符号和计算的方法

class BaseClass
    {
        /// <summary>
        /// 符号
        /// </summary>
        public string Symbol { get; set; }
 
        /// <summary>
        /// 计算方法
        /// </summary>
        /// <param name="a">其中一个值</param>
        /// <param name="b">另一个值</param>
        /// <returns></returns>
        public virtual float Calculation(float a, float b)
        {
            return 0;
        }
    }
接下来就是我们计算类,所有计算类都继承基类BaseClass
加法类
class Add : BaseClass
    {
        const string add = "+";
        public Add()
        {
            Symbol = add;
        }
        public override float Calculation(float a, float b)
        {
            return a + b;
        }
    }
减法类
class Sub : BaseClass
    {
        const string sub = "-";
        public Sub()
        {
            Symbol = sub;
        }
 
        public override float Calculation(float a, float b)
        {
            return a - b;
        }
    }
乘法类
class Mul : BaseClass
    {
        const string mul = "*";
        public Mul()
        {
            Symbol = mul;
        }
 
        public override float Calculation(float a, float b)
        {
            return a * b;
        }
    }
除法类
class Div : BaseClass
    {
        const string div = "/";
        public Div()
        {
            Symbol = div;
        }
        public override float Calculation(float a, float b)
        {
            if (0 == b)
            {
                return 0;
            }
 
            return a / b;
        }
    }
开方类
class Square:BaseClass
    {
        const string sub = "√";
        public Square()
        {
            Symbol = sub;
        }
        public override float Calculation(float a, float b)
        {
            return (float)Math.Sqrt(a);
        }
    }
定义好了计算类,现在要让程序知道,这些类叫什么名字,可以把它存在一个数组,链表,枚举里
我这里用枚举去存,个人爱好!
enum ClassName
    {
        Add,
        Sub,
        Mul,
        Div,
        Square
    }
现在计算类有了,类名也有了,接下来就是要实例化这些类,那就得用反射的原理了
/// <summary>
       /// 实例化ClassName里Add、Sub、Mul、Div、Square运算类
       /// </summary>
       /// <returns></returns>
       static List<object> InitBaseClass()
       {
           if (Enum.GetNames(typeof (ClassName)).Length == 0) return null;
 
           //定义BaseClass实例化
           List<object> bsList = new List<object>();
 
           // 获取当前方法的命名空间
           string nameSpace = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Namespace;
 
           //实例化ClassName里Add、Sub、Mul、Div、Square运算类
           foreach (var name in Enum.GetNames(typeof (ClassName)))
           {
               Type type = Type.GetType(nameSpace + "." + name); //获取类型
               bsList.Add(Activator.CreateInstance(type)); //根据类型创建实例
           }
 
           return bsList;
       }
类实例出来后,当我输入5+5时,程序就要自己去匹配加法类的计算方法,然后返回结果
/// <summary>
        /// 计算结果
        /// </summary>
        /// <param name="bsObjects">有多少个运算类</param>
        /// <param name="symbol">什么符号</param>
        /// <param name="num1">计算的数字一</param>
        /// <param name="num2">计算的数字二</param>
        /// <returns></returns>
        static object CalcResult(List<object> bsObjects, string symbol, float num1, float num2)
        {
            if (bsObjects.Count == 0 || string.IsNullOrEmpty(symbol)) return null;
 
            object result = null;
 
            foreach (var intance in bsObjects)
            {
                //获取的值是什么符号
                var symbolValue = intance.GetType().GetProperty("Symbol").GetValue(intance, null);
                //要调用那个运算类的方法
                if (Convert.ToString(symbolValue) == symbol)
                {
                    //调用类里的Calculation方法所获得的返回值
                    result = intance.GetType().GetMethod("Calculation").Invoke(intance, new object[] {num1, num2});
                }
            }
 
            if (result == null) return "没有正确的运算符!";
 
            return result;
        }
最后就是调用
static void Main(string[] args)
        {
            //存储实例化的计算类,只实例化一次
            List<object> bsObjects = InitBaseClass();
 
            //开线程调用计算方法
            //new Thread(() =>
            //{
            //    Console.WriteLine(CalcResult(bsObjects, "+", 5, 80));
            //})
            //{IsBackground = true}.Start();
 
            //调用计算方法
            object result = CalcResult(bsObjects, "√", 3, 8);
            Console.WriteLine(result);
 
            Console.ReadKey();
        }

结语:为什么要用反射,这样的好处就是我再添加其它运算类时,只需要继承BaseClass类,并自述自己是
用来做什么样的运算,即Symbol=“那种计算方式”,重写Calculation方法,并返回结果。实现计算类后,把
类名加 enum ClassName里面,就可以了,便于后期添加更多的计算类。

优化后《简单工厂模式》构造的计算器代码—C#“反射”技术(dll)

《大话设计模式》中的第一章是一个用简单工厂模式构建的简易计算器的例子,在书中的P10-P11页中有个工厂类OperaationFactory用来构造各个运算类的实例,但这里有个问题:如果需要增加新的运...

C#工厂模式_计算器

  • 2012年11月26日 09:34
  • 52KB
  • 下载

改良用简单工厂模式构造的计算器代码—“反射”技术

出处:http://blog.csdn.net/newjueqi/archive/2009/04/18/4089233.aspx 【文章标题】改良用简单工厂模式构造的计算器代码—“反射”技术 ...

简单工厂模式——MFC计算器实现(连续操作)

设计模式是重s

简单工厂模式---一个简单计算器的实现

1.面向对象编程    所有的编程初学者都会有这样的问题,就是碰到问题就直觉地用计算机能够理解的逻辑来描述和表达待解决的问题及具体的求解过程。这其实就是用计算机的方式去思考,是一种面向过程的开发方式,...

Java实现简单计算器功能【简单工厂模式】

Java实现简单计算器功能【简单工长模式】

实现工厂模式C#源码

  • 2011年06月10日 13:45
  • 4KB
  • 下载

设计模式之一:简单工厂模式,用python实现简易计算器

设计模式之一:简单工厂模式,用python实现简易计算器听说写技术博客对别人对自己都有好处,于是从这里开始写第一篇博客,记录自己的学习历程。由于编程功底很薄弱(对于代码的不足或错误,欢迎大家批评指正)...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C# 丢弃工厂模式,反射方式实现计算器
举报原因:
原因补充:

(最多只允许输入30个字)