银行业务调度系统 面试题思考

来源:互联网 发布:北京婚纱照价位 知乎 编辑:程序博客网 时间:2024/04/30 05:18

银行业务调度系统



模拟实现银行业务调度系统逻辑,具体需求如下:

银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。
有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。
异步随机生成各种类型的客户,生成各类型用户的概率比例为:
        VIP客户:普通客户:快速客户  =  1 :6 :3。

客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。
各类型客户在其对应窗口按顺序依次办理业务。
当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。
随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。
不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
    通过看了上面的面试题,经过了一些时间的思考,我用了C#简单地编写了一个。
    开发步骤:1、首先,根据系统的需求,分析一下类的设计,对于业务窗口类,我可以认为因为有3种类型的窗口,所以分为3种不同的银行员(Employee),它完成以下两件事:(1)从队列获取客户(GetCustomer),办理业务(DoBusiness)。对于客户(Customer)类,虽然有3种不同的客户,但是因为有共同点,所以不对其特征进行任何抽象,仅认为所有的客户都有一个需要办理的业务时间(BusinessTime)而已,当然,我们利用工厂模式,设一个CustomerFactory类,来产生3种不同的客户,并且把他们放到三个不同的队列中去。最后,我们还需创建一个Bank类用于保存三个客户队列,这里为了简单,我们创建三个全局静态队列
      2、理清业务逻辑:
      通过上面的分析,业务流程如下:
      Employee类是业务窗口,负责不停地查询三个队列,获取客户,然后针对客户办理业务,每个Employee实例都需要一个单独的线程。所以,有两种操作:GetCustomer和DoBusiness。
    Customer类则是很简单,仅仅有办理的业务时间(BusinessTime),保存在三个队列中。
    CustomerFactory类是一个单独的工厂类,用于随机生产不同的客户并把其加入到不同的队列中,这需要一个单独的线程来控制。
    Bank类保存三个客户队列,并且对其进行维护。
    3、进行编码
     首先编写Employee类,这里我想,先来编写普通业务窗口类,然后,VIP窗口和快速窗口继承自普通窗口。因为它们是泛化关系。源代码如下:
     普通业务窗口

view plaincopy to clipboardprint?
/// <summary>  
   /// 普通员工,普通业务窗口  
   /// </summary>  
   public class Employee  
   {  
       /// <summary>  
       /// 员工名  
       /// </summary>  
       public string Name  
       {  
           get;  
           set;  
       }  
 
       protected Thread thread;  
 
       public Employee()  
       {  
           thread = new Thread(new ThreadStart(DoBusiness));  
           thread.Start();  
       }  
       /// <summary>  
       /// 当前办理业务的客户  
       /// </summary>  
       protected Customer currentCustomer;  
         
 
       /// <summary>  
       /// 获取下一个要处理的客户  
       /// </summary>  
       protected virtual void GetCustomer()  
       {  
           currentCustomer = Bank.GetNormalCustomer();  
       }  
 
       protected void DoBusiness()  
       {  
           //不停地工作  
           while (true)  
           {  
               GetCustomer();  
               if (currentCustomer != null)//为客户办理业务  
               {  
                   Info.AddBeginBusinessInfo(this, currentCustomer);  
                   Thread.Sleep(currentCustomer.BusinessTime);  
                   Info.AddEndBusinessInfo(this, currentCustomer);  
               }  
           }  
             
       }  
 
       /// <summary>  
       /// 停止工作  
       /// </summary>  
       public void Stop()  
       {  
           thread.Abort();  
           thread.Join();  
       }  
   } 
VIP窗口和快速窗口继承自普通窗口,仅重写GetCustomer方法即可

/// <summary>  
/// VIP业务窗口  
/// </summary>  
public class VipEmployee:Employee  
{  
    protected override void GetCustomer()  
    {  
        currentCustomer = Bank.GetVipCustomer();//获取VIP客户  
        if (currentCustomer == null)  
        {  
              
            //没有VIP客户的情况下,获取普通客户  
            currentCustomer = Bank.GetNormalCustomer();  
        }  
    }  
}  
 
/// <summary>  
/// 快速业务窗口  
/// </summary>  
public class QuickEmployee:Employee  
{  
    protected override void GetCustomer()  
    {  
        currentCustomer = Bank.GetQuickCustomer();  
    }  
}
接着, 客户类Customer

/// <summary>  
/// 客户  
/// </summary>  
public class Customer  
{  
    /// <summary>  
    /// 客户名  
    /// </summary>  
    public string Name  
    {  
        get;  
        set;  
    }  
 
    /// <summary>  
    /// 客户办理业务所需的时间  
    /// </summary>  
    public TimeSpan BusinessTime  
    {  
        get;  
        set;  
    }  
}
然后,利用一个简单工厂生产客户Customer
view plaincopy to clipboardprint?
/// <summary>  
  /// 工厂生成类  
  /// </summary>  
  public class CustomerFactory  
  {  
      static TimeSpan totalWorkTime = new TimeSpan(0, 5,0);//总共工作5分钟  
      static TimeSpan interval = new TimeSpan(0, 0, 10);//每10秒产生一个客户  
      static TimeSpan maxTime=new TimeSpan(0,0,100);//客户最多办理业务100秒  
      static TimeSpan minTime=new TimeSpan(0,0,10);//客户最少办理业务10秒  
 
 
      static Random rnd = new Random();//随机种子  
      public static void CreateCustomer()  
      {  
          DateTime beginTime = DateTime.Now;  
          DateTime endTime = DateTime.Now;  
           
          Customer customer = null;  
          int count=1;//已生成客户的数量  
          while ((endTime - beginTime) < totalWorkTime)  
          {  
              //随机生成办理业务的时间  
              TimeSpan time=new TimeSpan(0,0,rnd.Next (minTime.Seconds,maxTime.Seconds+1));  
 
              switch (rnd.Next(10))  
              {  
                  case 0:  
                      customer = new Customer { Name = "VIP客户" + count.ToString(), BusinessTime = time };  
                      Bank.AddVipCustomer(customer);  
                      break;  
                  case 1:  
                  case 2:  
                  case 3:  
                  case 4:  
                  case 5:  
                  case 6:  
                      customer = new Customer { Name = "普通客户" + count.ToString(), BusinessTime = time };  
                      Bank.AddNormalCustomer(customer);  
                      break;  
                  default:  
                      customer = new Customer { Name = "快速客户" + count.ToString(), BusinessTime = minTime };  
                      Bank.AddQuickCustomer(customer);  
                      break;  
              }  
              count++;  
              Thread.Sleep(interval);  
              endTime = DateTime.Now;  
          }  
      }  
 
  } 


最好是Bank类。
view plaincopy to clipboardprint?
public class Bank  
   {  
       /// <summary>  
       /// 普通客户队列  
       /// </summary>  
       readonly static Queue<Customer> NormalCustomer;  
 
       /// <summary>  
       /// Vip客户队列  
       /// </summary>  
       readonly static Queue<Customer> VipCustomer;  
 
       /// <summary>  
       /// 快速客户队列  
       /// </summary>  
       readonly static Queue<Customer> QuickCustomer;  
 
 
       static Bank()  
       {  
           //初始化三个队列  
           NormalCustomer = new Queue<Customer>();  
           VipCustomer = new Queue<Customer>();  
           QuickCustomer = new Queue<Customer>();  
       }  
 
      /// <summary>  
      /// 从队列头获取普通客户,如果队列为空,返回null  
      /// </summary>  
      /// <returns>获取的客户</returns>  
       public static Customer GetNormalCustomer()  
       {  
           lock (NormalCustomer)  
           {  
               if (NormalCustomer.Count > 0)  
                   return NormalCustomer.Dequeue();  
               return null;  
           }  
       }  
 
       /// <summary>  
       /// 增加普通客户到队列尾部  
       /// </summary>  
       /// <param name="customer">要增加的客户</param>  
       public static void AddNormalCustomer(Customer customer)  
       {  
           Info.AddInfo(customer, NormalCustomer);  
           NormalCustomer.Enqueue(customer);  
 
       }  
 
 
       /// <summary>  
       /// 从队列头获取VIP客户,如果队列为空,返回null  
       /// </summary>  
       /// <returns>获取的客户</returns>  
       public static Customer GetVipCustomer()  
       {  
           lock (VipCustomer)  
           {  
               if (VipCustomer.Count > 0)  
                   return VipCustomer.Dequeue();  
               return null;  
           }  
       }  
 
       /// <summary>  
       /// 增加VIP客户到队列尾部  
       /// </summary>  
       /// <param name="customer">要增加的客户</param>  
       public static void AddVipCustomer(Customer customer)  
       {  
           Info.AddInfo(customer, VipCustomer);  
           VipCustomer.Enqueue(customer);  
 
 
       }  
 
 
       /// <summary>  
       /// 从队列头获取快速客户,如果队列为空,返回null  
       /// </summary>  
       /// <returns>获取的客户</returns>  
       public static Customer GetQuickCustomer()  
       {  
           lock (QuickCustomer)  
           {  
               if (QuickCustomer.Count > 0)  
                   return QuickCustomer.Dequeue();  
               return null;  
           }  
       }  
 
       /// <summary>  
       /// 增加快速客户到队列尾部  
       /// </summary>  
       /// <param name="customer">要增加的客户</param>  
       public static void AddQuickCustomer(Customer customer)  
       {  
           Info.AddInfo(customer, QuickCustomer);  
           QuickCustomer.Enqueue(customer);  
 
 
       }  
   } 
为了防止队列异常和多线程冲突,简单地封装了对三个队列的获取和加入方法。
其中的Info类是输出信息用的,比较简单,方便日后重构用的。
class Info  
{  
     public static void AddInfo(Customer customer,ICollection<Customer> queue)  
     {  
         Console.WriteLine("{0}:{1}加入等待队列,前面有{2}人等待。", DateTime.Now, customer.Name,queue.Count);  
     }  
 
     public static void AddBeginBusinessInfo(Employee employee, Customer customer)  
     {  
         Console.WriteLine("{0}:{1}开始为{2}办理业务。", DateTime.Now, employee.Name, customer.Name);  
     }  
 
     public static void AddEndBusinessInfo(Employee employee, Customer customer)  
     {  
         Console.WriteLine("{0}:{1}为{2}办理业务结束。", DateTime.Now, employee.Name, customer.Name);  
     }  

   class Info
    {
        public static void AddInfo(Customer customer,ICollection queue)
        {
            Console.WriteLine("{0}:{1}加入等待队列,前面有{2}人等待。", DateTime.Now, customer.Name,queue.Count);
        }

        public static void AddBeginBusinessInfo(Employee employee, Customer customer)
        {
            Console.WriteLine("{0}:{1}开始为{2}办理业务。", DateTime.Now, employee.Name, customer.Name);
        }

        public static void AddEndBusinessInfo(Employee employee, Customer customer)
        {
            Console.WriteLine("{0}:{1}为{2}办理业务结束。", DateTime.Now, employee.Name, customer.Name);
        }
    }
最后,在函数入库进行调用就行了。这样,基本上整个系统的功能实现了。

  static void Main(string[] args)  
{  
    List<Employee> all = new List<Employee>  
    {  
        new Employee { Name = "普通业务窗口1" },  
        new Employee { Name = "普通业务窗口2" },  
        new Employee { Name = "普通业务窗口3" },  
        new Employee { Name = "普通业务窗口4" },  
        new VipEmployee { Name = "VIP业务窗口" },  
        new QuickEmployee { Name = "快速业务窗口" }  
    };  
 
      
 
    Thread thd = new Thread(new ThreadStart(CustomerFactory.CreateCustomer));  
    thd.Start();  

    经过,对这个系统的分析,虽然,其中的有参考网上的资料,但是大部分都是自己深刻理解的,因此使我有很大收获,不仅对一个系统分析能力提高了,而且,也锻炼了我的代码编写能力。
 

原创粉丝点击