银行业务调度系统
模拟实现银行业务调度系统逻辑,具体需求如下:
银行内有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();
}
经过,对这个系统的分析,虽然,其中的有参考网上的资料,但是大部分都是自己深刻理解的,因此使我有很大收获,不仅对一个系统分析能力提高了,而且,也锻炼了我的代码编写能力。
模拟实现银行业务调度系统逻辑,具体需求如下:
银行内有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();
}
经过,对这个系统的分析,虽然,其中的有参考网上的资料,但是大部分都是自己深刻理解的,因此使我有很大收获,不仅对一个系统分析能力提高了,而且,也锻炼了我的代码编写能力。