戏说面向对象程序设计(C#版) 第五章 体会简单工厂模式的美妙

第五章    体会简单工厂模式的美妙

本文来自织梦

次日,小菜再来找大鸟,问道:“你昨天说计算器这样的小程序还可以用到面向对象三大特性?继承和多态怎么可能 内容来自dedecms

用得上,我实在不可理解。” 织梦内容管理系统

大鸟:“小菜很有钻研精神吗?好,今天我让你功力加深一级。你先要考虑一下,你昨天写的这个代码,能否做到

织梦内容管理系统

很灵活的可修改和扩展呢?” 本文来自织梦

小菜:“我已经把业务和界面分离了呀,这不是很灵活了吗?” 内容来自dedecms

大鸟:“那我问你,现在如果我希望增加一个开根(sqrt)运算,你如何改?”

copyright dedecms

小菜:“那只需要改Operation类就行了,在switch中加一个分支就行了。” dedecms.com

大鸟:“问题是你要加一个平方根运算,却需要把加减乘除的运算都得来参与编译,如果你一不小心,把加法运算

内容来自dedecms

改成了减法,这不是大大的糟糕。打个比方,如果现在公司要求你为公司的薪资管理系统做维护,原来只有技术人员(月 织梦内容管理系统

薪),市场销售人员(底薪+提成),经理(年薪+股份)三种运算算法,现在要增加兼职工作人员的(时薪)算法,但按

织梦内容管理系统

照你昨天的程序写法,公司就必须要把包含有的原三种算法的运算类给你,让你修改,你如果心中小算盘一打,‘TMD, 织梦内容管理系统

公司给我的工资这么低,我真是郁闷,这会有机会了’,于是你除了增加了兼职算法以外,在技术人员(月薪)算法中写 本文来自织梦

了一句 织梦好,好织梦

if(员工是小菜) 内容来自dedecms

    { 织梦内容管理系统

        salary = salary * 1.1;

dedecms.com

    }

织梦好,好织梦

那就意味着,你的月薪每月都会增加10%(小心被抓去坐牢),本来是让你加一个功能,却使得原有的运行良好的功能代 内容来自dedecms

码产生了变化,这个风险太大了。你明白了吗?”

本文来自织梦

小菜:“哦,你的意思是,我应该把加减乘除等运算分离,修改其中一个不影响另外的几个,增加运算算法也不影响 本文来自织梦

其它代码,是这样吗?” 内容来自dedecms

大鸟:“自己想去吧,如何用继承和多态,你应该有感觉了。”

copyright dedecms

小菜:“OK,我马上去写。” 内容来自dedecms

  内容来自dedecms

///     <summary> 本文来自织梦

///运算类 本文来自织梦

///     </summary>

copyright dedecms

class   Operation copyright dedecms

        { dedecms.com

private    double_numberA = 0;

织梦好,好织梦

private    double_numberB = 0; 织梦内容管理系统

 

织梦内容管理系统

///     <summary>

织梦好,好织梦

///数字A

本文来自织梦

///     </summary>

织梦内容管理系统

public   doubleNumberA

本文来自织梦

            { 织梦好,好织梦

get{      return_numberA; }

织梦内容管理系统

set{ _numberA =     value; }

本文来自织梦

            }

织梦内容管理系统

 

织梦内容管理系统

///     <summary> 本文来自织梦

///数字B 内容来自dedecms

///     </summary>

本文来自织梦

public   doubleNumberB

dedecms.com

            {

dedecms.com

get{      return_numberB; } copyright dedecms

set{ _numberB =     value; }

织梦内容管理系统

            } dedecms.com

  内容来自dedecms

///     <summary> copyright dedecms

///得到运算结果 本文来自织梦

///     </summary> 织梦内容管理系统

///     <returns></returns> copyright dedecms

public   virtual     doubleGetResult()

copyright dedecms

            {

织梦好,好织梦

doubleresult = 0;

织梦好,好织梦

returnresult; 本文来自织梦

            } 本文来自织梦

        } 本文来自织梦

 

内容来自dedecms

///     <summary> 织梦内容管理系统

///加法类 dedecms.com

///     </summary> 织梦好,好织梦

class   OperationAdd:   Operation

本文来自织梦

        { 内容来自dedecms

public   override    doubleGetResult() copyright dedecms

            { 本文来自织梦

doubleresult = 0; copyright dedecms

                result = NumberA + NumberB;

copyright dedecms

returnresult; 织梦好,好织梦

            } 织梦内容管理系统

        } 织梦内容管理系统

  内容来自dedecms

///     <summary>

copyright dedecms

///减法类

dedecms.com

///     </summary> dedecms.com

class   OperationSub:   Operation 织梦好,好织梦

        {

内容来自dedecms

public     override     doubleGetResult() 织梦好,好织梦

            {

copyright dedecms

doubleresult = 0;

内容来自dedecms

                result = NumberA - NumberB;

copyright dedecms

returnresult;

织梦好,好织梦

            }

织梦好,好织梦

        }

本文来自织梦

  织梦内容管理系统

///     <summary>

copyright dedecms

///乘法类

内容来自dedecms

///     </summary> dedecms.com

class   OperationMul:    Operation

本文来自织梦

        { 织梦内容管理系统

public   override    doubleGetResult() 内容来自dedecms

            { 织梦好,好织梦

doubleresult = 0;

dedecms.com

                result = NumberA * NumberB;

内容来自dedecms

returnresult; copyright dedecms

            } copyright dedecms

        } 本文来自织梦

 

本文来自织梦

///     <summary> 内容来自dedecms

///除法类 织梦好,好织梦

///     </summary> 织梦好,好织梦

class   OperationDiv:    Operation 织梦内容管理系统

        { 织梦好,好织梦

public     override     doubleGetResult()

copyright dedecms

            {

copyright dedecms

doubleresult = 0; 内容来自dedecms

if(NumberB == 0) 内容来自dedecms

throw  new           Exception("除数不能为0。");

织梦内容管理系统

                result = NumberA / NumberB;

dedecms.com

returnresult;

织梦好,好织梦

            }

本文来自织梦

        }

dedecms.com

小菜:“大鸟哥,我按照你说的方法写出来了一部分,首先是一个运算类,它有两个Number属性,主要用于计算器 copyright dedecms

的前后数,然后有一个虚方法GetResult(),用于得到结果,然后我把加减乘除都写成了运算类的子类,继承它后,重写

dedecms.com

了GetResult()方法,这样如果要修改任何一个算法,都不需要提供其它算法的代码了。但问题来了,我如何让计算器知

织梦内容管理系统

道我是希望用哪一个算法呢?” copyright dedecms

大鸟:“写得很不错吗,大大超出我的想象了,你现在的问题其实就是如何去实例化对象的问题,哈,今天心情不

本文来自织梦

错,再教你一招‘简单工厂模式’,也就是说,到底要实例化谁,将来会不会增加实例化的对象(比如增加开根运算),这 本文来自织梦

是很容易变化的地方,应该考虑用一个单独的类来做这个创造实例的过程,这就是工厂,来,我们看看这个类如何写。”

dedecms.com

  本文来自织梦

///     <summary> 织梦好,好织梦

///运算类工厂 内容来自dedecms

///     </summary>

copyright dedecms

class   OperationFactory 内容来自dedecms

    { 本文来自织梦

public   staticOperation createOperate(stringoperate) 织梦内容管理系统

        { 内容来自dedecms

            Operation oper =    null;

织梦内容管理系统

  copyright dedecms

switch(operate)

织梦内容管理系统

            { 内容来自dedecms

case  "+": 织梦内容管理系统

                    { 内容来自dedecms

                        oper =   newOperationAdd(); copyright dedecms

break;

内容来自dedecms

                    } 织梦好,好织梦

case  "-": 内容来自dedecms

                    {

织梦内容管理系统

                        oper =          newOperationSub();

织梦内容管理系统

break;

copyright dedecms

                    }

织梦内容管理系统

case  "*":

copyright dedecms

                    {

织梦好,好织梦

                        oper =          newOperationMul(); 织梦好,好织梦

break;

织梦内容管理系统

                    }

织梦好,好织梦

case  "/": 织梦好,好织梦

                    { copyright dedecms

                        oper =          newOperationDiv();

本文来自织梦

break; dedecms.com

                    }

内容来自dedecms

            } 本文来自织梦

  织梦内容管理系统

returnoper;

内容来自dedecms

        } copyright dedecms

    }

copyright dedecms

大鸟:“哈,看到吧,这样子,你只需要输入运算符号,工厂就实例化出合适的对象,通过多态,返回父类的方式 织梦好,好织梦

实现了计算器的结果。” 织梦内容管理系统

    Operation oper;

dedecms.com

    oper =   OperationFactory.createOperate("+"); copyright dedecms

    oper.NumberA = 1;

织梦好,好织梦

    oper.NumberB = 2;

织梦内容管理系统

doubleresult = oper.GetResult(); 本文来自织梦

大鸟:“哈,界面的实现就是这样的代码,不管你是控制台程序,Windows程序,Web程序,PDA或手机程序,都 本文来自织梦

可以用这段代码来实现计算器的功能,当有一天我们需要更改加法运算,我们只需要改哪里?”

织梦好,好织梦

小菜:“改OperationAdd    就可以了。”

copyright dedecms

大鸟:“那么我们需要增加各种复杂运算,比如平方根,立方根,自然对数,正弦余弦等,如何做?”

织梦内容管理系统

小菜:“只要增加相应的运算子类就可以了呀。”

dedecms.com

大鸟:“嗯?够了吗?” copyright dedecms

小菜:“对了,还需要去修改运算类工厂,在switch中增加分支。” 织梦好,好织梦

大鸟:“哈,那才对,那如果要修改界面呢?”

copyright dedecms

小菜:“那就去改界面呀,关运算什么事呀。” 本文来自织梦

小菜:“ 回想那天我面试题写的代码,我终于明白我为什么写得不成功了,原来一个小小的计算器也可以写出这么

内容来自dedecms

精彩的代码,谢谢大鸟。”

dedecms.com

  织梦好,好织梦

(下为当时面试题时小菜所写代码,见《小菜编程成长记(一)》) 本文来自织梦

Program 本文来自织梦

{ 本文来自织梦

static     voidMain(string[] args)

dedecms.com

    { copyright dedecms

Console.Write("请输入数字A:"); copyright dedecms

stringA =     Console.ReadLine();

内容来自dedecms

Console.Write("请选择运算符号(+、-、*、/):"); 内容来自dedecms

stringB =     Console.ReadLine(); 织梦好,好织梦

Console.Write("请输入数字B:");

织梦好,好织梦

stringC =     Console.ReadLine(); 内容来自dedecms

stringD =     "";

dedecms.com

 

本文来自织梦

if(B ==     "+")

copyright dedecms

            D =  Convert.ToString(Convert.ToDouble(A) +     Convert.ToDouble(C));

织梦好,好织梦

if(B ==     "-") dedecms.com

            D =     Convert.ToString(Convert.ToDouble(A) -            Convert.ToDouble(C)); dedecms.com

if(B ==     "*")

织梦好,好织梦

            D =     Convert.ToString(Convert.ToDouble(A) *            Convert.ToDouble(C)); 织梦内容管理系统

if(O ==     "/")

织梦好,好织梦

            D =     Convert.ToString(Convert.ToDouble(A) /            Convert.ToDouble(C));

本文来自织梦

 

copyright dedecms

Console.WriteLine("结果是:"+ D); dedecms.com

    } 织梦内容管理系统

}

本文来自织梦

大鸟:“吼吼,记住哦,编程是一门技术,更加是一门艺术,不能只满足于写完代码运行结果正确就完事,时常考 织梦好,好织梦

虑如何让代码更加简炼,更加容易维护,容易扩展和复用,只有这样才可以是真的提高。写出优雅的代码真的是一种很

内容来自dedecms

爽的事情。不过学无止境,其实这才是理解面向对象的开始呢。给你出个作业,做一个商场收银软件,营业员根据客户

织梦内容管理系统

购买商品单价和数量,向客户收费。”

织梦内容管理系统

小菜:“就这个?没问题呀。”

dedecms.com

精彩推荐
热点内容
最近更新