2010年5月18日 星期二

Design Pattern : 21 Proxy

有的物件在初始化時,需要消耗較大的系統效能,也比較花費時間
若要加速整個系統的初始化效能,不至於loading過久
如果可以讓物件在真正被使用時,才被實體化
那就可以加速整個系統的初始化載入
這就是Proxy Pattern所要提供的功能

原本的程式執行流程是,
一開始先初始化物件 real=new Real()
要執行功能時就呼叫物件的method real.method()
若改成利用Proxy Pattern
則是變成,在要執行物件的功能時
才去初始化物件實體,並呼叫其功能
而在這裡,讓功能物件與使用的Proxy繼承自相同的Interface
因為具備有相同的method

這樣你就可以在外部程式很輕鬆的切換並決定是否要使用proxy
或在Prxoy內作一些額外的處理後,再傳遞給真正的執行物件
參與者
1.Printable Interface
定義一個執行物件與Proxy的共通介面
public interface Printable {
    public void print(String msg);
}

2.Printer 真正的功能執行物件
實作介面所定義的必要功能
public class Printer implements Printable {
    @Override
    public void print(String msg) {
        System.out.print("Run Print="+msg);
    }
}

3.PrinterProxy
在Proxy內儲存了一個真正執行物件的實體(real)
而在實作功能上,才去初始化產生出物件
並執行功能
public class PrinterProxy implements Printable {
    private Printer real;
    @Override
    public void print(String msg) {        
        if(real==null){
            real=new Printer();            
        }
        real.print("From Proxy:"+msg);
    }
}

4.Main外部應用程式
可以很簡單的切換使用proxy或物件本體
去執行功能
public static void main(String[] args) {
    PrinterProxy myP=new PrinterProxy();
    //Printer myP=new Printer();
    myP.print("HELLO");
}

2010年5月17日 星期一

Design Pattern : 20 Flyweight

Flyweight的目的在減輕記憶體的使用量,
也就是減少new出新的物件佔據記憶體。

在整個Pattern的運作上,利用一個Factory Pool,
當需要新的物件會先向Factory查詢,
如果在Pool內已經存在,那就直接由pool內取得回傳,
若pool內沒有,才new出新物件,並存到pool內,
讓以後要用的可以取用
如此,所有相同的物件都只會被new出一個實體,
若有需要用到相同的實體,只需取用既有的instance即可

參與者
1.Animal 產生各式物件的Class
使用者要產生animal 實體,若在一般程式上會直接
new Animal,但在這Pattern下,new Animal動作是由
Factory來執行,而非由外部程式來直接產生物件
public class Animal {
    private String name;
    public Animal(String name){
        this.name=name;
        System.out.println(this.name+"--Created\n");
    }
    public void run(){
        System.out.print(this.name+"--run\n");
    }
}

2.Factory 管理所有物件的Factory
利用一個Hashtable當作pool來儲存可攻使用的instance
public class Factory {
    private Hashtable<String, Animal> pool=new Hashtable<String, Animal>();
    private static Factory instance=new Factory();
    public static Factory getInstance(){
        return instance;
    }
    public synchronized Animal getAnimal(String name){
        if(pool.get(name)==null){
            Animal tmpAnimal=new Animal(name);            
            pool.put(name,tmpAnimal);
            return tmpAnimal;
        }else{
            return pool.get(name); 
        }
    }
}

3.Main外部程式
public class Main {
    public static void main(String[] args) {
        Factory factory=Factory.getInstance();
        factory.getAnimal("man").run();
        factory.getAnimal("dog").run();
        factory.getAnimal("man").run();
        factory.getAnimal("cat").run();
        factory.getAnimal("dog").run();
        factory.getAnimal("dog").run();
    }
}
4輸出結果
由結果可以看出,每種animal都只會被產生一次
man--Created
man--run

dog--Created
dog--run

man--run

cat--Created
cat--run

dog--run

dog--run

2010年5月7日 星期五

Design Pattern : 19 State

如果在開發程式裡,會需要對不同的狀態,有不同的處理方式
可以把各種狀態的處理,各自包裝形成一個獨立的State Class
也就是說,透過State切割,把複雜的處理,切割成各自獨立小的區塊,
每個State很單純的處理該狀態下的執行功能,
以這方式執行,亦可很輕易的擴充程式功能

參與者
1.State 介面
定義出所有State所允許被呼叫的共同function
public interface State {
   public void showMessage(String user);
}

2.DayState 依照State實作出的Class
public class DayState implements State {
    private static DayState instance=new DayState();
    public static DayState getInstance(){
        return instance;
    }
    @Override
    public void showMessage(String user) {        
        System.out.println(user+" : Its Day");
    }
}

3.NightState 依照State實作出的Class
public class NightState implements State {
    private static NightState instance=new NightState();
    public static NightState getInstance(){
        return instance;
    }
    @Override
    public void showMessage(String user) {        
        System.out.println(user+" : its Night");
    }
}

4.MyFrame 使用State的主要程式
包含了setState function作為狀態轉移使用
在這裡要執行的動作,都只需要呼叫state的method即可,不需要
考慮真正的State實體是哪一個,
State的轉換都會透過外部呼叫setState來改變
public class MyFrame {
    private State state;
    public MyFrame(){}
    public void setState(String info){
        if(info=="day"){
            state=DayState.getInstance();
        }else{
            state=NightState.getInstance();
        }
    }
    public void showMessage(String user){
        state.showMessage(user);
    }
}

5.Main 外部程式
MyFrame frame=new MyFrame();
for(int hour=1;hour<=24;hour++){
    if((hour>=8)&&(hour<=18)){
        frame.setState("day");
    }else{
        frame.setState("night");
    }
    frame.showMessage("ozzy");
    try{
        Thread.sleep(1000);
    }catch(InterruptedException e){}
    
}

2010年5月6日 星期四

Always Somewhere - 大一印象

十月十號是放假的日子
宿舍裡是空空蕩蕩
住的近的都已經回家放假
外面的陽光是那麼的刺眼
穿著拖鞋,白色的汗衫,走下樓梯
理二社一樓總是比房間來的涼快

看看牆上留言箱,是否有新的小紙條在
踱出宿舍
大大的太陽,走過系館 走過外語學院
走過小巴黎 穿過圓環,走到校門口
穿過馬路 老葉牛肉麵 還開著
吃個麵 再到地面的雜貨舖買些生活用品

校門外的中正路上一樣車水馬龍
校園裡 安靜的似乎可以聽到風的聲音
再散步回宿舍
坐到桌前,把卡帶放到錄音機裡
1989年,在輔大的第一個連續假期
聽著Scorpions的Always Somewhere

2010年5月5日 星期三

Android,Flash,Java EventListener比較

在Flash,Java,Android上對於事件的處理
同樣使用Listener,有著類似但有些差異的語法
以下以常用的滑鼠click事件做簡單比較

一.Flash
Flash在對於所有的Event統一使用addEventListner method來做監聽
主要傳入的兩個參數,分別是要監聽的事件類型與要觸發的function


btn:Button=new Button();
addChild(btn);
btn.addEventListner(MouseEvent.CLICK,onClickHandler)
function onClickHandler(e:MouseEvent):void{
    //..do something..
}


二.Java
在Java上要監聽不同的事件,要使用不同的addXXXListener method
例如addActionListener,addWindowListener...
每個不同的addXXXListener method所接收的參數
都是不同的Listner物件instance,
所要執行的動作則是在這Listner物件內 implement
要監聽的動作 handler


Button btn=new Button();
add(btn);
btn.addActionListener(myactionListener);
ActionListener myactionListener=new ActionListener(){
    public void actionPerformed(ActionEvent e) {
        //..do something..
    }
}


三.Android
在Android上同樣是對不同的事件,有不同的setXXXListener
每個setXXXListener所接收參數都是不同的listener物件
與Java的差異是method名稱addXXXListener與setXXXListener
的不同而已
例setOnClickListener ,setOnFocuseChangeListener,
setKeyListener..


Button btn=(Button)findViewById(R.id.mybtnid);
btn.setOnClickListener(myclickListener);
Button.OnClickListener myclickListener=new Button.OnClickListener(){
    public void onClick(View v){
        //..do something..
    }
}