------- android培训、java培训、期待与您交流! ----------
个人小心得:
1. 面向对象思维:先不用考虑具体实现,而是应该先对项目进行需求分析,掘出并提取其中隐含的对象信息,和涉及到的主要功能
2. 功能封装:用对象封装功能,再对象互相调用或用一个主方法类进行综合调用;功能的封装遵循一个原则,谁拥有数据,谁就应该拥有操作数据的方法。
3. 代码实现和抽取:分析清楚后,就逐步对代码实现,最后对代码进行抽取和简化。
设计思路:
1. 对实际项目做需求分析。(题目已给出,此处省略)
2. 用面向对象的思想进行分析与设计。
3. 对抽象出的对象进行深入挖掘分析,提取出其他对象,和功能。
4. 具体实现的代码,留作参考。
项目需求略。
面向对象的分析:
1. 有三种对应类型的客户:VIP客户,普通客户,快速客户,异步随机生成各种类型的客户,各类型客户在其对应窗口按顺序依次办理业务 。
a) 这里涉及到一个主要的对象就是客户,但现实中每一个客户其实就是由银行的一个取号机器产生号码的方式来表示的。所以,要有一个号码管理器对象,让这个对象不断地产生号码,就等于随机生成了客户。这里提取了一个对象:号码管理器。
b) 由于有三类客户,每类客户的号码编排都是完全独立的,所以,要产生三个号码管理器对象,各自管理一类用户的排队号码。这三个号码管理器对象统一由一个号码机器进行管理,这个号码机器在整个系统中始终只能有一个,所以,它要被设计成单例。这里又涉及到一个对象:号码机器,单例设计模式。
2. 各类型客户在其对应窗口按顺序依次办理业务 ,实际上是窗口依次叫号。而各个窗口又是通过相应的号码管理器来确定叫哪一个号的,即服务窗口每次找号码管理器获取当前要被服务的号码。这里又涉及到一个对象:号码管理器
3. 涉及到了三种客户,可设计一个CustomerType枚举类
4. 为了增强程序的可扩展性,可以定义一个Constants类对用到的常量进行标示。
经过分析,有三个主要对象。
对象的深入分析设计:
NumberManager类
定义一个产生新号码的方法和获取马上要为之服务的号码的方法,这两个方法被不同的线程操作了相同的数据,所以,要进行同步。
既然产生了号码,就要定义一个用于存储上一个客户号码的成员变量和用于存储所有等待服务的客户号码的队列集合
NumberMachine类
定义三个成员变量分别指向三个NumberManager对象,分别表示普通、快速和VIP客户的号码管理器,定义三个对应的方法来返回这三个NumberManager对象。
将NumberMachine类设计成单例。所以还要私有化构造函数,在类内部定义一个自己的实例对象,并对外提供一个获取该对象的方法。
CustomerType枚举类
系统中有三种类型的客户,所以用定义一个枚举类,其中定义三个成员分别表示三种类型的客户。
重写toString方法,返回类型的中文名称。这是在后面编码时重构出来的,刚开始不用考虑。
ServiceWindow类
定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。
定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。
MainClass类
用for循环创建出4个普通窗口,再创建出1个快速窗口和一个VIP窗口。
接着再创建三个定时器,分别定时去创建新的普通客户号码、新的快速客户号码、新的VIP客户号码。
Constants类
定义三个常量:MAX_SERVICE_TIME、MIN_SERVICE_TIME、COMMON_CUSTOMER_INTERVAL_TIME
实现代码如下:可作为参考:
1、NumberManager类的实现
public class NumberManager {
private int lastNumber = 1;
private List<Integer> queueNumbers = new ArrayList< Integer >();
//定义产生号码的方法
public synchronized Integer generateNewNumber(){//因为和下面的获取号码的方法操作者同样的数据,所以要对方法加锁让两个方法(线程)互斥
queueNumber.add(lastNumber);
return lastNumber++;
}
//定义获取号码的方法,
public synchronized Integer fetchNumber(){
Integer number = null;
if(queueNumbers.size()>0){
number = queueNumber.remove(0);
}else{
return number;
}
}
}
2、NumberMachine类的实现
publicclass NumberMachine {
//定义自己的私有化构造方法,和实例对象,以及对外提供的返回该自身实例对象的方法
private NumberMachine(){}
privatestatic NumberMachineinstance = new NumberMachine();
publicstatic NumberMachine getInstance(){
returninstance;
}
//分别定义三中取号器对象 和对外提供获取的方法
private NumberManager commonManager =new NumberManager();
private NumberManager expressManager =new NumberManager();
private NumberManager vipManager =new NumberManager();
public NumberManager getCommonManager() {
returncommonManager;
}
public NumberManager getExpressManager() {
returnexpressManager;
}
public NumberManager getVipManager() {
returnvipManager;
}
}
3、CustomerType类的实现
publicenum CustomerType {
COMMON,EXPRESS,VIP;
//为了打印出的内容更人性化,此处覆盖toString方法
public String toString(){
String name=null;
switch(this){
case COMMON:
name= "普通";
break;
case EXPRESS:
name="快速";
break;
case VIP:
name=name();
break;
}
return name;
}
}
4、ServiceWindow类的实现
public class ServiceWindow {
private CustomerType type = CustomerType.COMMON;//指定窗口默认服务对象类型为普通,并在下面对外提供set方法修改该值。
private int number = 1;
public CustomerType getType() {
return type;
}
public void setType(CustomerType type) {
this.type = type;
}
public void setNumber(int number){
this.number = number;
}
public void start(){
Executors.newSingleThreadExecutor().execute(
new Runnable(){
publicvoid run(){
while(true){
switch(type){//用switch比if else效率高
case COMMON:
commonService();//进行代码抽出后的代码调用
break;
caseEXPRESS:
expressService();
break;
caseVIP:
vipService();
break;
}
}
}
}
);
}
//抽取的代码封装成一个单独的方法,提高代码的复用性
private void commonService(){
......
}
private void expressService(){
......
commonService();
}
}
private void vipService(){
......
commonService();
}
}
}
5、Constants类的实现
publicclass Constants {
public static int MAX_SERVICE_TIME = 10000; //10秒!
public stati cint MIN_SERVICE_TIME = 1000; //1秒!
public static int COMMON_CUSTOMER_INTERVAL_TIME= 1;
}
6、MainClass类的实现
public class MainClass {
public static void main(String[] args) {
//产生4个普通窗口
for(int i=1;i<5;i++){
ServiceWindow window = new ServiceWindow();
window.setNumber(i);
window.start();
}
//产生1个快速窗口
ServiceWindow expressWindow = new ServiceWindow();
expressWindow.setType(CustomerType.EXPRESS);
expressWindow.start();
//产生1个VIP窗口
ServiceWindow vipWindow = new ServiceWindow();
vipWindow.setType(CustomerType.VIP);
vipWindow.start();
//普通客户拿号
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
);
//快速客户拿号
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
);
//VIP客户拿号
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
);
}
}
代码实现以后,分析运行结果,然后进行多次调试和完善。这里还有一个待解决的问题,就是,因为CPU对线程的执行时间片段分配的问题,引起了先打印出为某人服务,再打印某人在等待的情况。