一张订单的生成(用面向对象思想设计订单类)

本文逐步介绍了如何设计一个能够自动生成订单流水号的订单类,并不断优化其结构以提高灵活性和扩展性。从最初的手动设置订单号到利用静态变量自动生成,再到引入接口以允许用户自定义流水号格式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当年有幸听了一堂微软MVP专家王豫祥老师的编程课,收益匪浅,现整理如下,供大家学习。

需求:设计一个订单类,该类可以实现自动的订单流水号。

1. 简单实现

namespace MyConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Order order1 = new Order();
            order1.BillNumber = "20160310-1";
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 1, order1.BillNumber, order1.CreateDate);
            System.Threading.Thread.Sleep(2000);

            Order order2 = new Order();
            order2.BillNumber = "20160310-2";
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 2, order2.BillNumber, order2.CreateDate);
            System.Threading.Thread.Sleep(2000);

            Order order3 = new Order();
            order3.BillNumber = "20130310-3";
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 3, order3.BillNumber, order3.CreateDate);

            Console.ReadLine();
        }
    }

    /// <summary>
    /// 订单
    /// </summary>
    public class Order
    {
        public string BillNumber
        {
            set;
            get;
        }

        public readonly DateTime CreateDate = DateTime.Now;
    }
}

不足现象:没有实现自动流水订单号


2. 提供自动流水订单号

namespace MyConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Order order1 = new Order();
            order1.BillNumber = order1.CreateBillNumber();
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 1, order1.BillNumber, order1.CreateDate);
            System.Threading.Thread.Sleep(2000);

            Order order2 = new Order();
            order2.BillNumber = order1.CreateBillNumber();

            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 2, order2.BillNumber, order2.CreateDate);
            System.Threading.Thread.Sleep(2000);

            Order order3 = new Order();
            order3.BillNumber = order1.CreateBillNumber();
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 3, order3.BillNumber, order3.CreateDate);

            System.Console.ReadLine();

        }
    }

    /// <summary>
    /// 订单
    /// </summary>
    public class Order
    {
        private static int count = 0;

        public string BillNumber
        {
            set;
            get;
        }

        public readonly DateTime CreateDate = DateTime.Now;

        public string CreateBillNumber()
        {
            count++;
            return DateTime.Now.ToString("yyyyMMdd-") + count.ToString();
        }
    }
}

产生流水的订单由其实例提供,这种模型不完善,不优雅


3. 静态实现订单流水号

namespace MyConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Order order1 = new Order();
            order1.BillNumber = order1.CreateBillNumber();
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 1, order1.BillNumber, order1.CreateDate);
            System.Threading.Thread.Sleep(2000);

            Order order2 = new Order();
            order2.BillNumber = order2.CreateBillNumber();

            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 2, order2.BillNumber, order2.CreateDate);
            System.Threading.Thread.Sleep(2000);

            Order order3 = new Order();
            order3.BillNumber = order3.CreateBillNumber();
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 3, order3.BillNumber, order3.CreateDate);

            System.Console.ReadLine();

        }
    }

    /// <summary>
    /// 订单
    /// </summary>
    public class Order
    {
        private static int count = 0;

        public Order()
        {
            count++;
        }

        public string BillNumber
        {
            set;
            get;
        }

        public readonly DateTime CreateDate = DateTime.Now;

        public string CreateBillNumber()
        {
            return DateTime.Now.ToString("yyyyMMdd-") + count.ToString();
        }
    }
}

不足现象:不能挑号


4. 构造函数赋值

namespace MyConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Order order1 = new Order();
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 1, order1.BillNumber, order1.CreateDate);
            System.Threading.Thread.Sleep(2000);

            Order order2 = new Order("dba");
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 2, order2.BillNumber, order2.CreateDate);
            System.Threading.Thread.Sleep(2000);

            Order order3 = new Order();
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 3, order3.BillNumber, order3.CreateDate);

            System.Console.ReadLine();

        }
    }

    /// <summary>
    /// 订单
    /// </summary>
    public class Order
    {
        private static int count = 0;

        /// <summary>
        /// 用户给定订单号
        /// </summary>
        /// <param name="number"></param>
        public Order(string number)
        {
            BillNumber = number;
        }

        /// <summary>
        /// 自动流水号
        /// </summary>
        public Order()
        {
            count++;
            BillNumber = CreateBillNumber();
        }

        public string BillNumber
        {
            set;
            get;
        }

        public readonly DateTime CreateDate = DateTime.Now;

        public string CreateBillNumber()
        {
            return DateTime.Now.ToString("yyyyMMdd-") + count.ToString();
        }
    }
}

实例Order时非常自然,如果没有在构造时赋值,则自动流水号产生,否则使用用户给予的号码。CreateBillNumber这个方法对用户透明了,因此我们可以直接封装这个方法。


5. 封装CreateBillNumber

namespace MyConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Order order1 = new Order();
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 1, order1.BillNumber, order1.CreateDate);
            System.Threading.Thread.Sleep(2000);

            Order order2 = new Order("dba");
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 2, order2.BillNumber, order2.CreateDate);
            System.Threading.Thread.Sleep(2000);

            Order order3 = new Order();
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 3, order3.BillNumber, order3.CreateDate);

            System.Console.ReadLine();

        }
    }

    /// <summary>
    /// 订单
    /// </summary>
    public class Order
    {
        private static int count = 0;

        /// <summary>
        /// 用户给定订单号
        /// </summary>
        /// <param name="number"></param>
        public Order(string number)
        {
            BillNumber = number;
        }

        /// <summary>
        /// 自动流水号
        /// </summary>
        public Order()
            : this(CreateBillNumber())
        {

        }

        public string BillNumber
        {
            set;
            get;
        }

        public readonly DateTime CreateDate = DateTime.Now;

        private static string CreateBillNumber()
        {
            count++;
            return DateTime.Now.ToString("yyyyMMdd-") + count.ToString();
        }
    }
}

对于用户的要求已经非常的贴切,如果是默认构造则产生自动流水订单号,否则使用用户给予的号码。而且,Order在构造时候,必须要求给予订单号(默认自动或用户指定),而且该订单号一旦产生就不可以变化。
缺陷:当用户要求流水号的格式有变化时,就会打破这个封装。而且由于static方法在继承上下不能被改变,所以不能通过子类来重写。


6. 接口提升封装

namespace MyConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Order order1 = new Order();
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 1, order1.BillNumber, order1.CreateDate);
            System.Threading.Thread.Sleep(2000);

            Order order2 = new Order("dba");
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 2, order2.BillNumber, order2.CreateDate);
            System.Threading.Thread.Sleep(2000);

            Order order3 = new Order(new InvoiceNumberFormat());
            Order order4 = new Order(new InvoiceNumberFormat());
            Order order5 = new Order(new InvoiceNumberFormat());
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 5, order5.BillNumber, order5.CreateDate);

            System.Console.ReadLine();
        }
    }

    public interface IOrderNumberFormat
    {
        string CreateBillNumber(int serialNumber);
    }

    public class InvoiceNumberFormat : IOrderNumberFormat
    {
        public string CreateBillNumber(int serialNumber)
        {
            return "***-" + serialNumber.ToString();
        }
    }

    /// <summary>
    /// 订单
    /// </summary>
    public class Order
    {
        private static int count = 0;

        /// <summary>
        /// 用户给定订单号
        /// </summary>
        /// <param name="number"></param>
        public Order(string number)
        {
            BillNumber = number;
        }

        /// <summary>
        /// 自动流水号
        /// </summary>
        public Order()
            : this(CreateBillNumber(CreateSerialNumber()))
        {

        }

        public Order(IOrderNumberFormat numberFormat)
            : this(numberFormat.CreateBillNumber(CreateSerialNumber()))
        {

        }


        public readonly string BillNumber;

        public readonly DateTime CreateDate = DateTime.Now;

        private static int CreateSerialNumber()
        {
            return ++count;
        }

        private static string CreateBillNumber(int serialNumber)
        {
            return DateTime.Now.ToString("yyyyMMdd-") + serialNumber.ToString();
        }
    }
}

到目前为止,Order关于订单的格式就完善多了,用户可以任意的扩展订单的流水格式,而又不破坏封装。


7. 优化接口实现

如果用户的前缀总是非常简单的字符串常数表达形式,则我们总是为一个简单的常数表达式去实现接口,增大了开销,因此我们优化接口的实现。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Order order1 = new Order("20130313-1");
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 1, order1.BillNumber,order1.CreateDate);
            System.Threading.Thread.Sleep(5000);

            Order order2 = new Order();
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 2, order2.BillNumber, order2.CreateDate);
            System.Threading.Thread.Sleep(5000);

            Order order3 = new Order(new InvoiceNumberFormat());
            Order order4 = new Order(new InvoiceNumberFormat());
            Order order5 = new Order(new InvoiceNumberFormat());
            Console.WriteLine("order{0} BillNumber is {1},CreateData at {2}", 5, order5.BillNumber, order5.CreateDate);

            System.Console.ReadLine();
        }
    }

    public interface IOrderNumberFormat
    {
        string CreateBillNumber(int serialNumber);
    }

    public class InvoiceNumberFormat : IOrderNumberFormat
    {
        public string CreateBillNumber(int serialNumber)
        {
            return "***-" + serialNumber.ToString();
        }
    }

    /// <summary>
    /// 订单
    /// </summary>
    public class Order
    {
        private static int count = 0;

        /// <summary>
        /// 用户给定订单号
        /// </summary>
        /// <param name="number"></param>
        public Order(string number)
        {
            BillNumber = number;
        }

        /// <summary>
        /// 自动流水号
        /// </summary>
        public Order()
            : this(CreateBillNumber(CreateSerialNumber()))
        {

        }

        public Order(IOrderNumberFormat numberFormat)
            : this(numberFormat.CreateBillNumber(CreateSerialNumber()))
        {

        }


        public readonly string BillNumber;

        public readonly DateTime CreateDate = DateTime.Now;

        private static int CreateSerialNumber()
        {
            return ++count;
        }

        private static string CreateBillNumber(int serialNumber)
        {
            return DateTime.Now.ToString("yyyyMMdd-") + serialNumber.ToString();
        }
    }

    public class StringOrderNumberFormat : IOrderNumberFormat
    {
        public readonly string FormatString;
        public StringOrderNumberFormat(string formatString)
        {
            FormatString = formatString;
        }

        public string CreateBillNumber(int serialNumber)
        {
            return FormatString + serialNumber.ToString();
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值