今天看了银行业务调度系统,觉得张老师真是个天才,我什么时候才能像张老师那样可以能做出这样的项目,缜密的思维,面向对象的信手拈来,都让我佩服的五体投地。
首先,看了两遍,代码能跟的上,但是思路就不行了,总结下我自己学到的知识吧。
从这个项目中学习到的编程思想:
如何用面向对象的方法去分析?
有三种对应类型的客户:VIP客户,普通客户,快速客户。三类客户,每类客户的号码编排都是完全独立的,那么本系统一共要产生三个号码管理器对象,各自管理一类用户的排队号码。这是本项目中的第三个对象。
这三个号码管理器对象统一由一个号码机器进行管理,这个号码机器在整个系统中始终只能有一个,所以,它要被设计成单例。
各类型客户在其对应窗口按顺序依次办理业务,谁是对象?人不是,因为只有窗口知道下一个该谁了,那么就是六个对象窗口。各个窗口怎么知道该叫哪一个号了呢?它一定是问的相应的号码管理器,即服务窗口每次找号码管理器获取当前要被服务的号码。也就是一共三类对象:号码机器他的功能是根据人数产生号码。被人取号码;
号码管理器有三个,功能分别给不同客户产生不同的号码。
窗口,三类,他要问号码管理器要要被服务的客户。他的功能是叫号。
他们三者之间的逻辑关系是:
NumberManager类
定义一个用于存储上一个客户号码的成员变量和用于存储所有等待服务的客户号码的队列集合。
定义一个产生新号码的方法和获取马上要为之服务的号码的方法,这两个方法被不同的线程操作了相同的数据,所以,要进行同步。
NumberMachine类
定义三个成员变量分别指向三个NumberManager对象,分别表示普通、快速和VIP客户的号码管理器,定义三个对应的方法来返回这三个NumberManager对象。
将NumberMachine类设计成单例。别人不能创建这个类的对象。
ServiceWindow类
定义一个start方法,内部启动一个线程,根据服务窗口的类别分别循环调用三个不同的方法。
定义三个方法分别对三种客户进行服务,为了观察运行效果,应详细打印出其中的细节信息。
MainClass类
用for循环创建出4个普通窗口,再创建出1个快速窗口和一个VIP窗口。
接着再创建三个定时器,分别定时去创建新的普通客户号码、新的快速客户号码、新的VIP客户号码。
从中学到的知识点:
第一:集合
public class NumberManager {
private int lastNumber = 1;
private List<Integer> queueNumber =new ArrayList<Integer>();
为了面向接口编程,不用变量的类型尽量面向父集,后者接口上一级。上级类型能干尽量用上级。而不要用子级,这样更灵活
也就是尽可能用超类。这样的细节更显专业。
publicsynchronized Integer generateNewManager(){自动拆箱装箱
我们每次产生一个号码,就把他存起来。
queueNumber.add(lastNumber);
return lastNumber++;队列是先加进去的先取出来,取走的东西的返回值就是这个东西本身
}
public synchronized IntegerfetchServiceNumber(){
Integer number = null;
if (queueNumber.size()>0){
number = queueNumber.remove(0);
第二:List集合
List集合排列是有序的,可以通过元素的角标位置查询获得这个元素,可以精确的对列表中元素的插入位置。但是这里remove的是角标为0的对象。返回的是被去掉的对象。
}
return number;
}
}
第三:线程同步
由于这是两个不同的线程在调用这个对象身上的两个不同的方法,这两个不同的线程访问了共享数据。就会出现第一个线程还没有执行完。另一个线程参与进来执行,导致共享数据的错误,就要加同步。
public classNumberMachine {
三个成员变量,
Private NumberManager commomManager
= new NumberManager();
private NumberManager expressManager = newNumberManager();
private NumberManager vipManager = newNumberManager();
public NumberManager getCommomManager() {
return commomManager;
}
public NumberManager getExpressManager() {
return expressManager;
}
public NumberManager getVipManager() {
return vipManager;
}
这个机器的对象只能有一个,所以我么要把它变成单例,先做成一个普通的对象,然后再把它变成单例模式
private NumberMachine(){}
private static NumberMachine instance =new NumberMachine();
public static NumberMachine getInstance(){
return instance;
}
第四:单例设计模式;
既然构造函数私有化了,别人就没法创建他,别人要想得到这个对象,只能调用它的静态方法
创建一个私有的静态的本类对象。想要得到它的方法,只有静态的能调用。这个静态方法返回他自己的一个对象。
第五:单个线程的线程池
里边只有一个单线程,我们创建一个线程池;它会自动调用里边的线程。
Executors.newSingleThreadExecutor().execute(newRunnable(){
Runnable接口实现对象实现Runnable的run方法;
public void run(){
while(true){
switch(type){
第六:switch的用法:
switch本来只能接受int short byte char;但是如果是枚举的话就可以接受类类型。
caseCOMMON:这里可以省略前缀
commonService();
break;
caseEXPRESS:
expressService();
break;
case VIP:
vipService();
break;
}
}
}
});
}
new Random().nextInt(10)+1 就是得到一个1到十之间的随即数字。
第七:枚举
这个类所有定义出来的变量的值只能是规定的那么几个。但是这个值不是普通的基本类型的值,而是对象类型的。这就是枚举,每一个枚举元素都是一个对象。
public enumCustomerType {
COMMON,EXPRESS,VIP;
publicString toString(){//他的toString方法返回的就是他的英文名字,但是中国喜欢看中文,所以要覆盖toString方法
switch(this){
case COMMON:
return "普通";
case EXPRESS:
return "快速";
case VIP:
return name();//枚举对象有个name方法就是返回自己的名字,
}
return null;
}
}
第八:常量大家要定一个专门的类
public classConstents{
public static int Max_SERVICE_TIME =10000;
public static int MIN_SERVICE_TIME =1000;
public static intCOMMON_CUSTOMER_INTERVAL_TIME = 1;}
第九:定时器的使用也是个线程池中的一个方法,
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
public void run(){
IntegerserviceNumber =NumberMachine.getInstance().getCommomManager().generateNewManager();
}
},
0, 过多少秒之后去干这个事
Constants.COMMON_CUSTOMER_INTERVAL_TIME,干完之后在过多少秒接着干?
TimeUnit.SECONDS这个是前面数字的计数单位
);
我目前对这个项目的理解还不是完全很透彻,不知道自己什么时候能独立的去编写类似于这种项目的代码。以后还会在仔细的回味这个视频,希望每次都能得到新的知识。
---------------------- android培训 、 java培训 、期待与您交流! ----------------------