zoukankan      html  css  js  c++  java
  • 构造函数的运用,体现类的自我维护

    构造函数有很多用处,巧妙地运用构造函数能提高类的设计安全、合理和封装。

    下面的类设计的不合理,要求用户在调用18行Pring方法前,先为17行赋值。
     1    public class Space
     2    {
     3
     4        public static void Main(string[] args)
     5        {
     6
     7            FilePrint pring = new FilePrint();
     8            //如果用户忘记调用FileName,系统将不可靠
     9            //pring.FileName = @"c:\text.txt";
    10            pring.Print();
    11        }

    12    }

    13
    14    public class FilePrint
    15    {
    16
    17        public string FileName = null;
    18        public void Print()
    19        {
    20            System.Console.WriteLine("Do prining {0}", FileName);
    21        }

    22    }
    把代码改为下面就合理的多
     1    public class Space
     2    {
     3
     4        public static void Main(string[] args)
     5        {
     6
     7            FilePrint pring = new FilePrint(@"c:\text.txt");
     8            pring.Print();
     9
    10            //代码可以更简约
    11            new FilePrint(@"c:\text.txt").Print();
    12        }

    13    }

    14
    15    public class FilePrint
    16    {
    17
    18        public FilePrint(string path)
    19        {
    20            FileName = path;
    21        }

    22
    23        public readonly string FileName = null;
    24        public void Print()
    25        {
    26            System.Console.WriteLine("Do prining {0}", FileName);
    27        }

    28    }

    通过构造函数,强制用户在实例化的时候给与FileName的值,调用更安全更简约。
    第23行对数据成员FileName修饰为readonly表示该数据成员为只读,只读的意思是,该成员只有一次赋值的机会(声明时立即赋值或在构造函数时赋值)。readonly和const的区别是
    readonly有两种赋值的机会:声明时立即赋值或在构造函数时赋值
    const只有在声明时赋值

    另外一个很值得注意的是,const其实就是static数据修饰,不过不能直接用static来修饰。const包括了static的含义,所以const需要通过类来访问。


    我们再来看一个构造函数的运用

    请仔细考虑一下代码
     1    public class Space
     2    {
     3
     4        public static void Main(string[] args)
     5        {
     6
     7            System.Console.WriteLine(new SalesContract(100).SalePrice);
     8            System.Console.WriteLine(new SalesContract(100,120).SalePrice);
     9            System.Console.WriteLine(new SalesContract(100,120,180).SalePrice);
    10
    11
    12        }

    13    }

    14
    15    public class SalesContract : Contract//销售合同 
    16    {
    17        public SalesContract(double costPrice)
    18            : this(costPrice, costPrice)
    19        { }
    20
    21        public SalesContract(double costPrice, double minimumPrice)
    22            : this(costPrice, minimumPrice, minimumPrice)
    23        { }
    24
    25        public SalesContract(double costPrice, double minimumPrice, double salePrice)
    26        {
    27            CostPrice = costPrice;
    28            MinimumPrice = minimumPrice;
    29            SalePrice = salePrice;
    30        }

    31
    32        private double MinimumPrice;//最低价
    33        public double SalePrice;//销售价格  
    34
    35        public bool CheckPrice()//价格检查
    36        {
    37            return SalePrice < Math.Min(MinimumPrice, CostPrice);
    38        }

    39        internal double PreferentialPrice;//优惠价
    40    }

    41
    42    public class Contract//合同
    43    {
    44
    45        public string Buyer;//买方
    46        public string Seller;//卖方
    47        protected double CostPrice;//成本价
    48    }


    通过3个构造函数,用户可以方便的对ConstPrice、SalePrice、MinimunPrice进行赋值。

    我们再来看一个关于构造函数的用例。

     1    public class Space
     2    {
     3
     4        public static void Main(string[] args)
     5        {
     6            System.Console.WriteLine(new Order("123-12").OrderNumber);
     7            System.Console.WriteLine(new Order(Order.CreateOrderNumber()).OrderNumber);
     8            System.Console.WriteLine(new Order(Order.CreateOrderNumber()).OrderNumber);
     9        }

    10    }

    11
    12    public class Order
    13    {
    14
    15        public Order(string orderNumber)
    16        {
    17            this.OrderNumber = orderNumber;
    18        }

    19
    20        private static int Count;
    21
    22        public readonly string OrderNumber;
    23
    24        public static string CreateOrderNumber()
    25        {
    26            System.DateTime d = System.DateTime.Now;
    27            return System.DateTime.Now.ToString("yMd-"+ (++Count).ToString();
    28        }

    29
    30    }

    上面的代码看似很合理,用户可以自己定义OrderNumber也可以通过CreateOrderNumber方法,Order在构造时总是可以得到Number。

    但这样的设计,暴露了对CreateOrderNumber的调用。

    我们看看经过修改后的设计

     1    public class Order
     2    {
     3
     4        public Order(string orderNumber)
     5        {
     6            this.OrderNumber = orderNumber;
     7        }

     8
     9        public Order():this(CreateOrderNumber())
    10        
    11        
    12        }

    13
    14        private static int Count;
    15
    16        public readonly string OrderNumber;
    17
    18        private static string CreateOrderNumber()
    19        {
    20            System.DateTime d = System.DateTime.Now;
    21            return System.DateTime.Now.ToString("yMd-"+ (++Count).ToString();
    22        }

    23
    24    }

    我们添加了一个默认的构造函数Order()在第9行,又把18行的CreateOrderNumber改为private,那么这会有什么效果呢?

     1    public class Space
     2    {
     3
     4        public static void Main(string[] args)
     5        {
     6            System.Console.WriteLine(new Order("123-12").OrderNumber);
     7            System.Console.WriteLine(new Order().OrderNumber);
     8            System.Console.WriteLine(new Order().OrderNumber);
     9        }

    10    }

    看到了吗?在这个代码中,如果用户给与了Number则使用用户给与的值,否则,Order能自动给与值。向用户封装了CreateOrderNumber的存在。这就是类设计的一个很重要的原则:自我维护。

  • 相关阅读:
    [非技术]简单预测中美关系未来的走向
    权限系统模型和常用权限框架
    [Tomcat]了解Tomcat,从它的结构开始
    [Mybatis]用AOP和mybatis来实现一下mysql读写分离
    [MQ]说一说MQ消息积压
    [MQ]再谈延时队列
    [Web] 浅谈Cookie,Session,Token
    k8s搭建
    微信公众平台开发(2)扫描二维码添加公众账号
    微信公众平台开发模式
  • 原文地址:https://www.cnblogs.com/shyleoking/p/644049.html
Copyright © 2011-2022 走看看