Re: 不懂如何抽離物件(初學物件導向的問題)

作者: sunneo (艾斯寇德)   2008-09-02 17:48:50
其實你可以爬文看看之前的文章,大概都有寫的很清楚,
除了封裝可以把事情都包在一起外,重要的就是polymophism的地方,就是一個介面,
比如說程式碼裡面有好幾個地方都長的很像,為了避免copy-paste之嫌,所以
把同樣的部分抽出來成為caller,不同的部分成為abstract callee method.
然後之後的實作只是把callback的部分實體化。
caller就依照他預先想好的行為來叫用。
舉個系統模擬的例子。
今天要實作演算法,分別是First Come First Service,Shortest Job First,
Round Robin
剛開始的時候真的就一個一個寫出來。
假設facility本身就會紀錄進入時間以及離開時間,產生critical section
並且製作critirial report.
void fcfs(){
require(facility);
advance(time_slice);
release(facility);
}
void sjf(){ // Shortest Job First
set_priority(-time_slice);
require(facility);
advance(time_slice);
release(facility);
}
void rr(){ // Round Robin
double my_time = min(time_slice,std_time_slice);
for(;;){
require(facility);
advance(my_time);
time_slice -= my_time;
release(facility);
if(time_slice) yield();
else terminate();
}
}
這裡知道Round Robin中間有部分不一樣,其他都很像,於是改為
void rr_helper(){
time_slice -= my_time;
release(facility);
if(time_slice) yield();
else terminate();
}
void rr(){
for(;;){
require(facility);
double my_time = min(time_slice,std_time_slice);
advance(my_time);
release(facility);
rr_helper();
}
}
然後sjf只有剛開始設定優先權跟fcfs不一樣,所以把設定優先權抽了出來
抽為init
所以sjf改為如下
void sjf(){
init();
require(facility);
advance(time_slice);
release(facility);
}
於是流程就變成如下,這時候fcfs已經可以跟sjf用下面的介面完成了。
void init(){
set_priority(-time_slice);
}
void sche_alg(){
init();
require(facility);
advance(time_slice);
release(facility);
}
然後為了rr可以同時使用,將time_slice改為my_time,用for(;;)包起流程
並且增加了一個get_new_time_slice();
將after_release加入
void rr::rr_helper(){
time_slice -= my_time;
release(facility);
if(time_slice) yield();
else terminate();
}
void fcfs::after_release(){
terminate();
}
void rr::after_release(){
rr_helper();
}
void sche_alg(){
init();
for(;;){
require(facility);
get_new_time_slice();
advance(my_time);
release(facility);
after_release();
}
}
終於完成了,可喜可賀...
以class來呈現就如下
class Schedule_Algorithm: public SLX::Puck{
protected:
double my_time,time_slice;
virtual after_release(){ terminate(); }
virtual void get_new_time_slice(){}
public:
FCFS(double tm_slice) :my_time(tm_slice),time_slice(tm_slice){}
virtual void action(){
for(;;){
require(facility);
get_new_time_slice();
advance(my_time);
release(facility);
after_release();
}
}
};
class FCFS: public Schedule_Algorithm {
public:
FCFS(double tm_slice): Schedule_Algorithm(tm_slice){}
};
class SJF: public FCFS{
public:
SJF(double tm_slice):FCFS(tm_slice){
set_priority(-tm_slice);
}
};
class RR: public FCFS{
enum rr_config{ std_time_slice=5 };
public:
virtual void after_release(){
time_slice -= my_time;
release(facility);
if(time_slice) yield();
else terminate();
}
RR(double tm_slice):FCFS(tm_slice){}
void get_new_time_slice(){
my_time = min(time_slice,(double)std_time_slice);
}
};
花了些時間,終於是都抽出來了,後來才發現抽出來實在沒有必要。
因為他們都是演算法,以後又多了演算法,那麼基本流程(action)還是得被改過一次.
所以可以先看看有沒有必要抽離出來,否則作了也是浪費時間。

Links booklink

Contact Us: admin [ a t ] ucptt.com