黑马程序员-银行管理面试题总结

-------  android培训 java培训 、期待与您交流! ---------- 
面向对象的分析与设计:

下面是张孝祥老师的经典例子,可以让我们更深入的理解,面向对象的分析和设计。

一个重要的经验就是谁拥有数据,谁就提供操作数据的方法。

1,两块石头磨成一把刀,石刀可以砍树,砍成木材,木材做成椅子。

stone  石头不能自己把自己变成石刀。

stoneknife    可以通过石刀加工场让石头变成石刀 =knifeFactory.creatKnife(stone,stone);

tree

material   石刀可以拥有砍的方法,通过这个方法把树变成木材。=stoneknife.cut(tree)

chair 椅子也需要一个加工场来吧木材变成椅子。=chairFactory.makeChair(material);

好了,看完了上面的例子,我们来跟着张老师来完成这个管理系统。

首先需求:

 

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

          银行内有6个业务窗口,1 - 4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口。

          有三种对应类型的客户:VIP客户,普通客户,快速客户(办理如交水电费、电话费之类业务的客户)。

          异步随机生成各种类型的客户,生成各类型用户的概率比例为:

         VIP客户 :普通客户 :快速客户  =  1 :6 :3。

         客户办理业务所需时间有最大值和最小值,在该范围内随机设定每个VIP客户以及普通客户办理业务所需的时间,快速客户办理业务所需时间为最小值(提示:办理业务的过程可通过线程Sleep的方式模拟)。

          各类型客户在其对应窗口按顺序依次办理业务。

          当VIP(6号)窗口和快速业务(5号)窗口没有客户等待办理业务的时候,这两个窗口可以处理普通客户的业务,而一旦有对应的客户等待办理业务的时候,则优先处理对应客户的业务。

          随机生成客户时间间隔以及业务办理时间最大值和最小值自定,可以设置。

          不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。

根据分析,我们首先设计好自己的思路。

第一点,我们要有个数据管理系统,即NumberManager,

然后这个管理系统要被一个机器返回你具体要那个数据管理系统。NumberMachine

这时我们还需要客户的对象类,我们要根据这个类,来向机器所要具体的数据管理系统。

最后我们就需要一个服务窗口,ServerWindow

分析到这基本可以写了,要是写的过程发现少点什么可以在添加。但是大致方向已经定好了。

数据管理类:

import java.util.*;
public class NumberManager {

 private int lastNumber=0;//设置一个数值,相当于来银行办理业务的客户。
 private List<Integer> queueNumber=new ArrayList<Integer>();
 public synchronized Integer gengerateNewManager(){//考虑到线程安全加同步锁,因为可能多客户同时进入等待区
  queueNumber.add(++lastNumber);//将客户加入到等待区
  return lastNumber;
 }
 public synchronized Integer fetchServiceNumber(){//考虑到线程安全加同步锁,因为可能多窗口同时呼叫客户
  if(queueNumber.size()>0){
   return (Integer)queueNumber.remove(0);//呼叫客户到窗口办理业务。
  }else{
   return null;
  }
 }
}

这个类看着还简单吧,就是一个存和取的过程。

public class NumberMachine {
 //分别创建管理对象示例,每个管理对象示例负责不同的客户群。
 private NumberManager commonManager=new NumberManager();
 private NumberManager expressManager=new NumberManager();
 private NumberManager vipManager=new NumberManager();
 public NumberManager getCommonManager() {
  return commonManager;
 }
 public NumberManager getExpressManager() {
  return expressManager;
 }
 public NumberManager getVipManager() {
  return vipManager;
 }
 private NumberMachine(){}//相同的客户群用的是同一个管理器,所以这设计成单例模式
 public static NumberMachine getInstance(){
  return instance;
 }
 private static NumberMachine instance=new NumberMachine();
 
}

这段代码也比较简单,很好懂就不多说了。

用枚举类列出3中客户类型:

public enum CustomerType {
 COMMON,EXPRESS,VIP;
 public String toString(){
  switch(this){
  case COMMON:
   return "普通";
  case EXPRESS:
   return "快速";
  case VIP:
   return name();    
  }
  return null;
 }
}

好了,前奏完了,下面才是最重要的环节,ServerWindow服务窗口,其实这才是中枢系统。

import java.util.Random;
import java.util.concurrent.Executors;


public class ServiceWindow {
 private CustomerType type = CustomerType.COMMON;//创建客户类型,并初始化为普通客户。
 private int windowId = 1;//窗口编号

 public void setType(CustomerType type) {//设置客户类型
  this.type = type;
 }

 public void setWindowId(int windowId) {//设置窗口编号
  this.windowId = windowId;
 }

 public void start() {//银行开门,开始上班了
  Executors.newSingleThreadExecutor().execute(new Runnable() {//创建线程池。
   @Override
   public void run() {
    // TODO Auto-generated method stub
    //通过客户类型判断启动哪个服务窗口
    while (true) {
     switch (type) {
     case COMMON:
      commonServer();
      break;
     case EXPRESS:
      expressServer();
      break;
     case VIP:
      vipServer();
      break;
     }
    }
   }

  });
 }

 private void commonServer() {//普通客户服务区,
  System.out.println("第" + windowId + "号" + type + "窗口" + "正在获取普通任务");
  Integer number = NumberMachine.getInstance().getCommonManager()
    .fetchServiceNumber();//从普通客户管理器中获取客户号
  if (number != null) {//如果不是null,则为其服务
   long beginTime = System.currentTimeMillis();//纪录开始时间
   try {
    Thread.sleep((new Random()//采用随机数来模拟服务时间。
      .nextInt(Constancs.MAX_SERVICE_TIME + 1))//这是一个常量,放在常量类里面。
      + Constancs.MIN_SERVICE_TIME);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   long endTime = (System.currentTimeMillis() - beginTime)/1000;//纪录结束时间
   System.out.println("第" + windowId + "号" + type + "窗口" + "为第" + number + "个" + "普通"
     + "客户服务,用时" + (int)endTime + "秒");//输出服务信息

  } else {//如果没有客户,就休息一秒在重新查看管理器
   System.out.println("没有取到任务,休息1秒");
   try {
    Thread.sleep(Constancs.MIN_SERVICE_TIME);//这是一个常量,放在常量类里面。
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }
 private void expressServer() {//快速服务区,下面基本和上面一样,只把不一样的地方标示下。
  System.out.println("第" + windowId + "号 快速窗口" + "正在获快速取任务");
  Integer number = NumberMachine.getInstance().getExpressManager()
    .fetchServiceNumber();
  if (number != null) {
   long beginTime = System.currentTimeMillis();
   try {
    Thread.sleep(Constancs.MIN_SERVICE_TIME);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   long endTime = (System.currentTimeMillis() - beginTime)/1000;
   System.out.println("第" + windowId + "号" + type + "窗口" + "为第" + number + "个" + type
     + "客户服务,用时" +(int) endTime + "秒");

  } else {//如果没有快速客户,则帮普通客户办理业务。普通客户没有在休息。
   commonServer();
  }
 }
 private void vipServer() {//VIP客户区,下面基本同上面
  //String windowName = "第" + windowId + "号" + type + "窗口";
  System.out.println("第" + windowId + "号VIP窗口" + "正在获取VIP任务");
  Integer number = NumberMachine.getInstance().getVipManager()
    .fetchServiceNumber();
  if (number != null) {
   long beginTime = System.currentTimeMillis();
   try {
    Thread.sleep((new Random()
      .nextInt(Constancs.MAX_SERVICE_TIME + 1))
      + Constancs.MIN_SERVICE_TIME);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   long endTime = (System.currentTimeMillis() - beginTime)/1000;
   System.out.println("第" + windowId + "号" + type + "窗口" + "为第" + number + "个" + type
     + "客户服务,用时" + (int)endTime + "秒");

  } else {//如果没有VIP客户,则办理普通业务,没有在休息。
   commonServer();
  }
 }
}

到这里就差不多完成了多一半了,下面补充一个常量类,是为了以后修改代码方便而提取出来的。

public class Constancs {
 public static int MAX_SERVICE_TIME=10000;//模仿服务时间的最大值
 public static int MIN_SERVICE_TIME=1000;//模仿服务时间的最小值
}

哈哈,还少一个主程序就完成了,暗爽一下吧。

import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class MainBank {
 public static void main(String[] args) {
  for(int i=1;i<5;i++){//采用循环的模式启动4个普通窗口
   ServiceWindow commomWindow=new ServiceWindow();
   commomWindow.setWindowId(i);
   commomWindow.start();
  }
  ServiceWindow expressWindow=new ServiceWindow();
  expressWindow.setWindowId(5);//启动5号快速窗口
  expressWindow.setType(CustomerType.EXPRESS);
  expressWindow.start();
  
  ServiceWindow vipWindow=new ServiceWindow();
  vipWindow.setWindowId(6);//启动6号VIP窗口
  vipWindow.setType(CustomerType.VIP);
  vipWindow.start();
  
  //创建3个定时器,模拟3种客户进入到等候区。
  Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
    new Runnable() {
     @Override
     public void run() {
      Integer number=NumberMachine.getInstance().getCommonManager().gengerateNewManager();
      
      
     }
    },
    0,
    1,//普通客户每一秒钟来一个
    TimeUnit.SECONDS);
  Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
    new Runnable() {
     @Override
     public void run() {
      Integer number=NumberMachine.getInstance().getExpressManager().gengerateNewManager();
      
      
     }
    },
    0,
    2,//快速客户每两秒一个
    TimeUnit.SECONDS);
  Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
    new Runnable() {
     @Override
     public void run() {
      Integer number=NumberMachine.getInstance().getVipManager().gengerateNewManager();
     }
    },
    0,
    6,//VIP客户每6秒一个。
    TimeUnit.SECONDS);
 }

}

------------- java培训android培训、期待与您交流! -------------


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值