设计模式(一)—简单工厂(创建型)

  • 一、定义       

             简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

     该模式中包含的角色及其职责

    1. 工厂(Creator)角色

    简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。

    1. 抽象产品(Product)角色

    简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

    1. 具体产品(Concrete Product)角色

    是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。

    二、图分析

           

    1、运算类与简单工厂为依赖关系,即简单工厂类使用到运算类。简单工厂类并不知道具体实例化哪一个类,所以通过返回运算类用到哪个类就实例化哪个类。

    2、其他算法类继承于运算类,具有相同的方法

    三、代码实现

    namespace 简单工厂模式
    
    {
    
        class Program
    
        {
    
            static void Main(string[] args)
    
            {
    
                              Operation oper;                                                                   //声明对象
    
                oper=OperationFactory.createOperate("+");      //决定实例化哪一个运算类
    
                oper.NumberA=1;
    
                oper.NumberB=2;
    
                double result = oper.GetResult();                      //获得结果
    
                Console.WriteLine("结果是:" + result);
    
                Console.ReadLine();       
    
            }
    
        }
    
        public class Operation                //运算类
    
     
    
     
    
        {
    
            private double _numberA = 0;   
    
            private double _numberB = 0;
    
     
    
            public double NumberA
    
           {
    
             get{ return _numberA;}
    
             set{ _numberA = value;}
    
           }
    
            public double NumberB
    
           {
    
             get{ return _numberB;}
    
             set{_numberB = value;}
    
           }
    
           public virtual double GetResult()          //获得结果的方法
    
           {
    
              double result=0;
    
              return result;
    
            }
    
        }
    
       class OperationAdd:Operation             //继承运算累
    
      {
    
        public override double GetResult()
    
         {
    
             double result=0;
    
             result = NumberA + NumberB;
    
             return result;
    
          }
    
       }
    
     
    
       class OperationSub : Operation           //继承运算类
    
      {
    
        public override double GetResult()
    
         {
    
             double result=0;
    
             result = NumberA - NumberB;
    
             return result;
    
          }
    
       }
    
     
    
       class OperationMul : Operation             //继承运算类
    
      {
    
        public override double GetResult()
    
         {
    
             double result=0;
    
             result = NumberA * NumberB;
    
             return result;
    
          }
    
       }
    
     
    
       class OperationDiv : Operation               //继承运算类
    
      {
    
        public override double GetResult()
    
         {
    
             double result = 0;
    
             if(NumberB==0)
    
                 throw new Exception("除数不能为0.");
    
             result = NumberA / NumberB;
    
             return result;
    
          }
    
       }
    
     
    
      public class OperationFactory                      //简单工厂
    
      {
    
         public static Operation createOperate(string operate)
    
         {
    
           Operation oper=null;
    
           switch(operate)
    
           {
    
               case"+":
    
               oper=new OperationAdd();
    
               break;
    
               case"-":
    
               oper=new OperationSub();
    
               break;
    
               case"*":
    
               oper=new OperationMul();
    
               break;
    
               case"/":
    
               oper=new OperationDiv();
    
               break;
    
             }
    
            return oper;
    
         }
    
          }
    
    }

    四、适用情况(联系生活和以前学习经验)

    1. 工厂类负责创建的对象比较少;
    1. 客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;
    1. 由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。
    1. 简单的组合查询应该会遇到(自己的理解,如果不正确请谅解)

    五、知识点归纳

    1、静态变量的使用

              在C#程序中,没有全局变量的概念,这意味着所有的成员变量只有该类的实例才能操作这些数据,这起到了“信息隐藏”的作用。但有些时候,这样做却不是个明智的选择。

              假设我们要定义一个图书类,要求该类能保存图书的数量,即每增加一本图书(定义一个实例),图书的数量应该加1。如果没有静态变量,我们需要将图书的数量保存在每本图书(实例)里,然而,这样的变量要在不同图书(实例)里重复存储,图书(实例)数量少的话,我们还能接受,如果图书(实例)数量较多的话,比如成千上万,我们无法想象这要造成多少资源(如内存、磁盘空间)的浪费,更让人无法忍受的是:因为图书(实例)的数量要保存在每本图书(实例)里,该值肯定是不同的。要使这些图书(实例)中保存的图书(实例)数量一致,我们必须在每增加一本新书(生成一个新实例)时,修改其他所有图书(实例)中保存的该值。Oh,My God!你会重新向往面向过程的程序设计方法,向往拥有全局变量的时代。但,这种局面不会出现,因为C#中为你准备好了另外一种变量类型:静态变量。它在类中类似全局变量,保存类的公共信息,所有该类的实例(对象)共享该值。

     

    静态变量的声明方式如下:

     

    [访问修饰符] static 数据类型 变量名;

     

    这里的访问修饰符跟类的其它成员一样,可以是public,protected,private或internal等。

     

    静态变量又如何使用呢?

     

    静态变量必须使用类名来引用,而不能使用类的实例,因为,静态变量不属于任何实例,而是共有的。我们可以打个比方:在一个班级中,有些物品是个人的,我们想使用时,必须指出物品的所有者,比如说“王三的自行车”,在C#程序中我们可以使用:王三.自行车的格式。有些物品是大家共有的物品,不能以个人名义使用,而是用班级的名义使用,比如班集体出资买的篮球,只能说:“班级的篮球”,而不能说:“王三的篮球”。这绝对是不行的,这对其他人绝对是不公平的,我们可以联想到许多贪官污吏就是使用了不属于自己的东西,或以个人名义使用公家的东西而葬送了自己。

     

    说一句有用的就是:静态变量是用类名来引用它。即:类名.静态变量名;

     

    另外,对于静态变量在声明时,如果没有给出初始值或使用前没有赋任何值的话,系统会给他们一个默认值:对于整型数据默认值为0;单精度数据为:0.0f;双精度数据为0.0;布尔型数据为False;引用型数据为null。

     

    2.静态方法

     

    静态方法与静态变量一样,不属于任何特定的实例,属于类全体成员共有,由类名来调用。但要注意以下几点:

     

    静态方法只能访问类的静态成员,不能访问类的非静态成员;

     

    非静态方法可以访问类的静态成员,也可以访问类的非静态成员;

     

    静态方法不能使用实例来调用,只能使用类名来调用。这里用一个具体的例子来说明:

     

     2、0d的思考

            对于静态变量在声明时,如果没有给出初始值或使用前没有赋任何值的话,系统会给他们一个默认值:对于整型数据默认值为0;单精度数据为:0.0f;双精度数据为0.0;布尔型数据为False;引用型数据为null。

            0d和0.0d的区别:需要的精度不同

    3、封装的两种形式

    两种封装方法(引用信秀)

        传统的读、写方法封装:

       

           //有一个类Name,为了操纵这个类中的数据(string name)我们定义了一个读方法和一个写方法。  
            public class Name  
            {  
    
                private string name;  
    
                // 读方法  
                public string GetName()  
                {  
                    return name;  
                }  
                //写方法  
                public void SetName(string n)  
                {  
                    name = n;  
    
                }  
    
                public static void Main(string[] args)  
                {  
                    Name Country = new Name();  
                    Country.SetName("China");  
                    Console.WriteLine("The Name is :" + Country.GetName());  
                }  
        }  
    
        上面的方法保证了私有成员name不被外部成员所破坏,我们实例化一个对象Country来实现读和写数据。在上面的例子中,我们不能直接访问类Name 的实例Country中的私有数据(string name),我们只能通过SetName和GetName两个方法来读和写数据。
    
       用属性来实现封装:
    
        属性是类的基本组成部分,通过对属性的读和写来保护类中的域。使用属性来实现封装比上一种方法更简单。
    
        public class Name  
        {  
            private string name;  //需要封装的属性  
            public string CountryName  
            {  
    
                get{return name;}  
    
                set{name=value;}  
            }  
        }  
        public class Name1  
        {  
            public static void Main(string[] args)  
            {  
                Name Country= new Name();  
                Country.CountryName = "China";  
                Console.WriteLine("The Country is :{0}",Country.CountryName);  
            }  
        }    

         上面的例子通过属性实现了stringname的封装,其中属性具有两种操作get和set。Get用来返回属性域的值;Set通过value这个变量来给属性域赋值。

    4、多态实现的四种形式

    接口多态性。

    • 继承多态性。
    • 通过抽象类实现的多态性。
    • 虚方法

    5、null的思考

    1. 等价于没有任何值、是未知数(Empty代表瓶子是空的,null代表瓶子都没有)。
    1. NULL与0、空字符串、空格都不同,NULL没有分配存储空间。
    1. 对空值做加、减、乘、除等运算操作,结果仍为空(此设计模式设计的)
    1. NULL的处理使用NVL函数。
    1. 比较时使用关键字用“is null”和“is not null”。
    2. 空值不能被索引,所以查询时有些符合条件的数据可能查不出来,count(*)中,用nvl(列名,0)处理后再查。
    3. 排序时比其他数据都大(索引默认是降序排列,小→大),所以NULL值总是排在最后。
    1.  Null代表未初始化的引用类型成员

            引用类型成员并不一定会在定义或构造函数中就初始化。一种情况,是为了性能考虑,进行延时初始化,如单例模式中。但是,null值不应该传递给外部。

           另一种情况,是考虑扩展性,将个别成员留空。如适配器模式中,Asp.Net Page在呈现时,会检查其Adapter属性是否为null,如不是null,则调用Adapter负责呈现。

    1. 尽可能减少返回null的场景

             留意了下.Net Framework的函数,返回null的还真是很少见。一返回null,调用函数就不得不进行判断,增加了复杂性,及出错的机率。通过对代码结构进行适当调整优化,应该可以减少null的判断。尤其是框架开发,在公开的API函数中,返回Null的情况应该越少越好。例外的可能是一些按索引取值的属性,如HttpRequest.Form。

     

      如果是要返回一个集合类型,只要执行无异常,宁可为空也不要返回null。

    1. 要对外部数据进行null判断

    在你公开的API中,必须考虑被其他程序集调用,接收到null参数的情况,不管是什么原因传入的。

    不要让null参数表示特殊含义

    1. 让程序抛出ArgumentNullException而不是NullReferenceException

    六、出错点

    1、客户端调试时没有输出结果

    2、UML图中返回类型不显示:通过return和显示operation

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值