??xml version="1.0" encoding="utf-8" standalone="yes"?>成人亚洲一区二区,国产在线播放精品,国产一级免费在线观看http://www.aygfsteel.com/jesson2005/category/21670.htmlN文hQ乃市井一俗h也,ȝ卷书Q跨江河千里Q故甛_一游; 一两滴辛酸Q三四年学业Q五六点_墨Q七八笔买卖Q九十道人情?/description>zh-cnWed, 18 Apr 2007 06:45:23 GMTWed, 18 Apr 2007 06:45:23 GMT60Design Pattern: Decorator 模式http://www.aygfsteel.com/jesson2005/articles/111179.html张金?/dc:creator>张金?/author>Tue, 17 Apr 2007 02:44:00 GMThttp://www.aygfsteel.com/jesson2005/articles/111179.htmlhttp://www.aygfsteel.com/jesson2005/comments/111179.htmlhttp://www.aygfsteel.com/jesson2005/articles/111179.html#Feedback0http://www.aygfsteel.com/jesson2005/comments/commentRss/111179.htmlhttp://www.aygfsteel.com/jesson2005/services/trackbacks/111179.html
JTextArea textArea = new JTextArea();
JScrollPane scrollPane = new JScrollPane(textArea);
 
JScrollPaneJTextAreax個容器,而它JFrame來說又是個元Ӟ可以如下這般之加入JFrame中:
getContentPane().add(scrollPane);
 
像這樣動態的為JTextArea加入功能的方法,我們可以用Decorator模式來組J結構,您可以動態的Z個物件加入一些功能(像是?JTextArea加上捲軸Q,而又不用修改JTextArea的功能。對JTextArea來說QJScrollPane好像是一個捲軸外框,直接套在JTextArea上作裝飾Q就好比您在照片上加上一個相框的意思?br>
先以上面這個例子來說明Decorator模式的一個實例:
Decorator

如上圖所C的Q無論是TextView或是Decorator別Q它們都是VisualComponent的一個子,也就是說它們都是一個可視元Ӟ而Decorator又聚合了VisualComponentQ所以又可以當作TextView容器QScrollDecorator別實作?Decorator,它可能是這樣a計的:
public abstract class Decorator extends VisualComponent {
    protected VisualComponent component;

    public Decorator(VisualComponent component) {
        this.component = component;
    }

    public void draw() {
        component.draw();
    }
}

public class ScrollDecorator extends Decorator {
    public ScrollDecorator(VisualComponent component) {
        super(component);
    }

    public void draw() {
        super.draw();
        scrollTo();
    }

    public void scrollTo() {
        // ....
    }
}
 
要將新功能套用至TextView上,可以這樣a計Q?br>
ScrollDecorator scrollDecorator =
                    new ScrollDecorator(new TextView());
 
super.draw()會先呼叫component也就是TextView物g的draw()Ҏ先繪製TextViewQ然後再進行 ScrollPanel的scrollTo()Q也是捲動的方法。在圖中也表CZ一個BorderDecoratorQ它可能是這樣a計的:
public class BorderDecorator extends Decorator {
    public BorderDecorator(VisualComponent component) {
        super(component);
    }

    public void draw() {
        super.draw();
        drawBorder();
    }

    public void drawBorder() {
        // ....
    }
}
 
要將ScrollDecorator與BorderDecorator加至TextView上,我們可以這樣a計Q?br>
BorderDecorator borderDecorator =
         new BorderDecorator(
               new ScrollDecorator(new TextView()));

所以當BorderDecorator調用draw()Ҏ時,它會先調用ScrollDecorator的draw()ҎQ?ScrollDecorator的draw()Ҏ又會先調用TextView的draw()ҎQ所以繪製的順序變成Q?br>
TextDraw.draw();
ScrollDecorator.scrollTo();
BorderDecorator.drawBorder();

下圖為物件之間的調用關係Q?br>
Decorator

Decorator模式?UML i構圖如下所C:
Decorator

在Gof的書中指出另一個範例,它設a一個Stream抽象,而有一個StreamDecorator,Stream的子有處理a憶體串的 MemoryStream與FileStreamQ有各種Ҏ可以處理串流Q也a只是單純的處理字元Q也a會進行壓縮Q也a會進行字元轉換Q最基本的處理可能是處理字元Q而字元壓^被視為外的功能,這個時候我們可以用裝飾模式,在需要的時候為Stream物g加上必要的功能,事實上在java.io中的a多輸入輸出物gQ就是採取這樣的設a?br>

]]>
Design Pattern: Flyweight 模式http://www.aygfsteel.com/jesson2005/articles/111180.html张金?/dc:creator>张金?/author>Tue, 17 Apr 2007 02:44:00 GMThttp://www.aygfsteel.com/jesson2005/articles/111180.htmlhttp://www.aygfsteel.com/jesson2005/comments/111180.htmlhttp://www.aygfsteel.com/jesson2005/articles/111180.html#Feedback0http://www.aygfsteel.com/jesson2005/comments/commentRss/111180.htmlhttp://www.aygfsteel.com/jesson2005/services/trackbacks/111180.htmlGof 的書中指出,Flyweight的目的在於運用共享技術,使得一些細_度的物件可以共享?br>
Flyweight在牛z字怸的解釋是"boxer of the lightest class"。意思是特輕量級x手?其實應該是取"the lightest class"這部份的解釋Q一個特輕量級類別,這個類別所產生的物件可以共用在每一個場合(contextQ,並依場合資訊表現物g外觀?br>
在書中所舉出的例子是文檔R輯器中的字元物Ӟ若每個字元物件會包括字元、大、字型等{不同的資訊Q想想一文章中可能出現多少字元Q如果我們為每一個字元都使用一個物件來完整描述有關於它的訊息,那麼一文字中會耗用多少的記憉Q!字元本n應可以共享,而大、字型等{不同的資訊再分別設定?br>
考慮敔R多且性質相近的物件時Q將該物件的資訊分為兩個部份:內部狀態(intrinsicQ與外部狀態(extrinsicQ。以上例來說Q字元屬於內部狀態,而大、字型等{不同的資訊屬於外部狀態?br>
更詳C些來說明Q內部狀態是物g可共享的a息部䆾Q例如在J製一個英文字串時Q重覆的字元部䆾為內部狀態,像是 "ABC is BAC"Q其中A、B、C的字元資a部份不必直接儲存於字元物g中,它是屬於可以׃n的部份,可以這些可以重複使用的字元儲存在Flyweight Pool中?br>
外部狀態是物g依賴的一個場景(contextQ,例如J製字元時的字型資訊、位|資a等{,J製一個字元時Q先從Flyweight Pool中找出共享的FlyweightQ然後從場景中查扑ְ應的J製資訊Q字型、大、位|等Q?br>
其實M孔RJava的h׃定用過Java中運用Flyweight模式的好處,要知道,如果您在E式中用下面的方式來宣告,則實際上是指向同一個字串物Ӟ
String str1 = "flyweight";
String str2 = "flyweight";
System.out.println(str1 == str2);
 
E式的執行結果會示TrueQ在Java中,會維護一個String PoolQ對g些可以共享的字串物gQ會先在String Pool中查找是否存在相同的String內容Q字元相同)Q如果有q接傳回,而不是直接創造一個新的String物gQ以減少a憶體的耗用?br>
再來個一看例子,String的intern()ҎQ我們來看看它的API說明的節錄:
Returns a canonical representation for the string object.

A pool of strings, initially empty, is maintained privately by the class String.

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

這段話其實已說明了Flyweight模式的運作方式,用個實例來說明會更清楚Q?br>
  • Main.java
public class Main { 
public static void main(String[] args) {
String str1 = "fly";
String str2 = "weight";
String str3 = "flyweight";
String str4;

str4 = str1 + str2;
System.out.println(str3 == str4);

str4 = (str1 + str2).intern();
System.out.println(str3 == str4);
}
}

在程式中W一ơ比較str3與str4物g是否為同一物g時,您知道結果會是falseQ而intern()Ҏ會先檢查 String Pool中是否存在字元部份相同的字串物gQ如果有的話傳回,由於E式中之前已E有"flyweight"字串物gQintern()在String Pool中發現了它,所以直接傳回,這時再進行比較Qstr3與str4所指向的其實是同一物gQ所以結果會是true?br>
Flyweight模式在傳回物件時Q所使用的是工廠模式Q用者並不會知道物g被創造的細節Q下圖是Flyweight模式的結構圖Q?
Flyweight

之前舉的例子是針物件的內部狀態所作的說明Q那麼字型資a等外部的設定呢Q一兩個簡單的外部資訊a定可以直接寫死Qhard codeQ在E式中,例如單的用介面字型設定?br>
但如果是文書處理器呢Q用者設定字型、大等資訊會是動態的呢QGof怸字型資a作為是J製字元的外部狀態,使用一個Context 物g來維護外部狀態資料nQ每ơ要J製字元物g時,這個Context物g會被作為參數傳遞i字元物Ӟ字元物g透過查找Context中的資料來獲得字型資a,從而進行正確的場景繪製?br>
外部狀態維譯內部狀態之間的應關係Q在查找時,Gof怸所使用的是BTree?i構Q由於查扑ֿ須花L間,所以這也指出了用Flyweight 模式所必須付出的代價:以時間換取空間。如何設a外部狀態的資料i構Q以使得查找時間^短Q這是另一個重要的課題Q不過就不是這篇文章要討論的課題了)?br>
補充Q關於字元(內部狀態)及字型、大(外部狀態)之間的對應問通常不太需要程式設ah員的關心Q因為通常可以扄C些現成的圖型介面APIQ它們都a計好一些相關元Ӟ直接使用可以了?br>

]]>
Design Pattern: Bridge 模式http://www.aygfsteel.com/jesson2005/articles/111177.html张金?/dc:creator>张金?/author>Tue, 17 Apr 2007 02:42:00 GMThttp://www.aygfsteel.com/jesson2005/articles/111177.htmlhttp://www.aygfsteel.com/jesson2005/comments/111177.htmlhttp://www.aygfsteel.com/jesson2005/articles/111177.html#Feedback0http://www.aygfsteel.com/jesson2005/comments/commentRss/111177.htmlhttp://www.aygfsteel.com/jesson2005/services/trackbacks/111177.htmlGof 的書中指到Bridge模式的目的:「將抽象部䆾與它的實N份分離,使它們都可以獨立地變化。?br>
這句話寫得簡短,這邊再作進一步的解釋Q抽象部份指的是行為斚w定義Q實現方面指的是與特定^台相依的代碼實現?br>
一個實際的例子在Gof怸有提刎ͼ假設您定了一個IWindow介面Q這個介面只定義一些抽象的J圖行為Q而不涉及q_的實作,今天您可以繼扉K個類來開發適用於X Window的XWindow,也可以繼扉K個類來開發適用於Windows XPpȝ的WindowsXP,Z善用pȝ資源Q您在實作IWindow介面時,會將與系iq關的實現代碼撰寫在介面的實作中?br>
Bridge

假設今天您繼承了IWindow介面撰寫了一個I3DWindow介面Q當中擴充一個drawBox()Ҏ用於3D圖Ş的繪製,單的說Q?I3DWindow介面擴充了抽象行為,Z讓實現I3DWindow的類別也能在XWindow與Windows XP兩個不同的pȝ中運行,您必須再度撰寫與pȝ盔R的實現代{?br>
Bridge

單的說Q抽象行為定與q_盔R實現混雜在一起了Q為了將抽象部䆾與它的實N份分離,使它們都可以獨立地變化,您可以用以下的i構?br>
Bridge

在上圖的右邊中,與^台相關的實現部䆾Q被與右邊抽象行斚w的發展分開了Q左邊的抽象部䆾您可以一直發展下去,而不再因為綁定了q_特定實作ҎQ而得整個結構越來越失去彈性?br>
Bridge模式?UML 別i構圖如下:
Bridge



]]>
Design Pattern: Composite 模式http://www.aygfsteel.com/jesson2005/articles/111178.html张金?/dc:creator>张金?/author>Tue, 17 Apr 2007 02:42:00 GMThttp://www.aygfsteel.com/jesson2005/articles/111178.htmlhttp://www.aygfsteel.com/jesson2005/comments/111178.htmlhttp://www.aygfsteel.com/jesson2005/articles/111178.html#Feedback0http://www.aygfsteel.com/jesson2005/comments/commentRss/111178.htmlhttp://www.aygfsteel.com/jesson2005/services/trackbacks/111178.html
於使用者而言Q無論是文字、線D|h形,甚至是組合後的圖片元Ӟ它們都擁有一個共同的行為Q用者基本上並不會感覺出它們之間的操作有Q何的不同Q您可以拖曳、放大、縮等{,這些行為都是一致的?br>
?UML 來表CZ面這個例子的i構Q?
Composite

於Text、Line與Rectangle而言QPicture是一個容器,然而PictureJ承Graphic,所以它也是一個繪圖元Ӟ您可以進一步的Picturei合臛_一個Picture中,以Ş成較大的、複雜的圖Ş?br>
i合模式的UMLi構圖如下所C:
Composite

依此架構Q您可以遞迴的組合圖形元Ӟ例如Q?br>
Composite

除了J圖元g之外Q一些具有層ơ性或i合性的物g也可以用Composite模式Q像是電路元件、設備元件等{,使用Composite模式可以大大減低這些元ga計的複雜度?br>

]]>
Design Pattern: Adapter 模式 - Object Adapterhttp://www.aygfsteel.com/jesson2005/articles/111175.html张金?/dc:creator>张金?/author>Tue, 17 Apr 2007 02:41:00 GMThttp://www.aygfsteel.com/jesson2005/articles/111175.htmlhttp://www.aygfsteel.com/jesson2005/comments/111175.htmlhttp://www.aygfsteel.com/jesson2005/articles/111175.html#Feedback0http://www.aygfsteel.com/jesson2005/comments/commentRss/111175.htmlhttp://www.aygfsteel.com/jesson2005/services/trackbacks/111175.html
似的概念,有時候您惛_原來的程式中加入一個外部元Ӟ例如一個類別,但是這個類別與您目前所a計的程式在介面上並不一_Z讓這個外部類與原E式的介面一_您必須用一個類別作Z介來配接它們,這時您可以採用Adapter模式?br>
舉個例子來說,在Java 1.0中有個EnumerationQ您在這個版本發行之後,使用它來a計了一個MessageApplicationQ例如:
  • MessageApplication.java
import java.util.*;

public class MessageApplication {
public void showAllMessage(Enumeration enum) {
Object msg;
while(enum.hasMoreElements()) {
msg = enum.nextElement();
System.out.println(msg);
}
}
}

您的客戶端程式是這麼使用MessageApplication的:
  • MessageClient.java
import java.util.*;

public class MessageClient {
private MessageApplication msgApp;

public void run() {
Vector vector = new Vector();
for(int i = 0; i < 10; i++)
vector.addElement("物g " + i);

msgApp = new MessageApplication();
msgApp.showAllMessage(vector.elements());
}

public static void main(String[] args) {
MessageClient msgClient = new MessageClient();
msgClient.run();
}
}

珑֜Java 1.2中新增了IteratorQ您惌使用它的功能Q但基本上您不想更動原來E式中已a計好的MessageApplication別Q這時候您可以使用Adapter模式Q將Iterator的介面轉換為Enumeration相容Q例如:
  • IteratorAdapter.java
import java.util.*;

public class IteratorAdapter implements Enumeration {
private Iterator iterator;

IteratorAdapter(Iterator iterator) {
this.iterator = iterator;
}

// 轉接介面
public boolean hasMoreElements() {
return iterator.hasNext();
}

public Object nextElement()
throws NoSuchElementException {
return iterator.next();
}
}

您可以在客戶端程式中照樣使用MessageApplication別Q而不用作M的變動:
  • MessageClient.java
import java.util.*;

public class MessageClient {
// We could still use MessageApplication
private Enumeration iteratorAdapter;

public void run() {
List arrayList = new ArrayList();

for(int i = 0; i < 10; i++)
arrayList.add("物g " + i);

iteratorAdapter =
new IteratorAdapter(arrayList.iterator());
// We could still use MessageApplication
MessageApplication msgApp = new MessageApplication();
msgApp.showAllMessage(iteratorAdapter);
}

public static void main(String[] args) {
MessageClient msgClient = new MessageClient();
msgClient.run();
}
}

 

如程式所C的Q透過Adapter模式Q您原有E式中已a計好的別不用更動Q就可以引進新別的功能,上面的E式UML別i構畫出如下Q?br>
Adapter

上面的作法,是將要引進的新類別當作Adapter別的一個物件成員,這是IbObject Adapter模式Q其抽象i構如下Q?br>
Adapter


]]>
Design Pattern: Adapter 模式 - Class Adapterhttp://www.aygfsteel.com/jesson2005/articles/111176.html张金?/dc:creator>张金?/author>Tue, 17 Apr 2007 02:41:00 GMThttp://www.aygfsteel.com/jesson2005/articles/111176.htmlhttp://www.aygfsteel.com/jesson2005/comments/111176.htmlhttp://www.aygfsteel.com/jesson2005/articles/111176.html#Feedback0http://www.aygfsteel.com/jesson2005/comments/commentRss/111176.htmlhttp://www.aygfsteel.com/jesson2005/services/trackbacks/111176.html
Adapter

C++中可以多重繼承,但在Java中不行,所以在Java中若要採用Class AdapterQ必須作點修改,一斚wJ承AdapteeQ一斚w實作Target的介面:
Adapter

代碼的實現是這樣的: 
public class Adapter extends Adaptee implements Target {
    // ....
}

當然Q這必須您原先的Target定義了共同的介面Q所以Class Adapter在Java中適用的場合較少Q事實上Q也比較使用Object AdapterQ這樣的Adapter模式比較有彈性,例如Q您可以在Adapter上加上個setterQ以隨時可以抽換Adaptee?br>
在Java中,Class Adapter的一個應用場合是達到多重J承的效果,您一定在很多時候聽別h說,介面QinterfaceQ可以達到多重繼承的效果Q這是怎麼回事Q?br>
其實要討論這個問,首先您對於C++中多重繼承要先有認識Q新手看了書說介面可以達到多重繼承,切莫Z亦云Q尤其是沒有孔RC++的新手們,如果您對於C++多重J承惌有所認識Q請先看?多重J承Q一Q?/a>?多重J承Q二Q?/a>?br>
Java不能多重J承Q但Z說Java中可以用介面(interfaceQ來達到多重J承的效果,首先效果之一Q就?
多重J承Q二Q?/a> 中描q的「多重繼承時通常其中一個基底類別作為private實作體,而其它的用以表現完全的抽象介面。」,在Java中這個效果可以用介面來達到Q介面此時所扮演的即 多重J承Q二Q?/a> 中的抽象別Q一個完全的抽象介面Q這個效果的達成方式Q如 介面QinterfaceQ型?/a> 中所介紹的,您可以直接對應這兩個主中的程式實作來瞭解Q瞭解Java中如何用介面(interfaceQ來達到C++中所多重繼承的「一E」效果?br>
來看看另一個情況?br>
如果有SomeClass別與OtherClass別Q您惌SomeAndOther別可以同時擁有SomeClass別?OtherClass別中已定義好的操作Q並可以進行多型操作Q在C++中可以用多重J承來達刎ͼ但在Java中顯然的無法使用多重J承Q怎麼辦?您可以在a計上先J個彎Q先使用兩個介面分別定好SomeClass與OtherClass兩個類別的公開ҎQ例如:
public interface ISome {
    public void doSome();
}

public interface IOther {
    public void doOther();
}

接著讓SomeClass與OtherClass分別實作兩個介面:
public class SomeClass implements ISome {
    public void doSome() {
        ....
    }
}

public class OtherClass implements IOther {
    public void doOther() {
        ....
    }
}

SomeAndOther如何同時擁有兩個SomeClass與OtherClass別已定好的操作?並可以多型操作?SomeAndOther可以J承其中之一Q並擁有其中之一Q例如:
public class SomeAndOther extends SomeClass implements IOther {
    private IOther other = new OtherClass();

    public void doOther() {
        other.doOther();
    }
}

雖不滿意Q但臛_解決了目前的問題Q當焉邊只是其中一例,畢竟C++是C++QJava是JavaQ兩者語法並不是一一的關係,視實際需求還可以變化一下?br>


]]>
Design Pattern: Default Adapter 模式http://www.aygfsteel.com/jesson2005/articles/111174.html张金?/dc:creator>张金?/author>Tue, 17 Apr 2007 02:40:00 GMThttp://www.aygfsteel.com/jesson2005/articles/111174.htmlhttp://www.aygfsteel.com/jesson2005/comments/111174.htmlhttp://www.aygfsteel.com/jesson2005/articles/111174.html#Feedback0http://www.aygfsteel.com/jesson2005/comments/commentRss/111174.htmlhttp://www.aygfsteel.com/jesson2005/services/trackbacks/111174.html
public interface WindowListener extends EventListener {
    public void windowOpened(WindowEvent e);
    public void windowClosing(WindowEvent e);
    public void windowClosed(WindowEvent e);
    public void windowIconified(WindowEvent e);
    public void windowDeiconified(WindowEvent e);
    public void windowActivated(WindowEvent e);
    public void windowDecativated(WindowEvent e);
}
 
可以定義一個類別來實作這個介面,以完全想要的事g處理Q例如:
public class WindowEventHandler implements WindowListener {
    public void windowOpened(WindowEvent e) {}
    public void windowClosing(WindowEvent e) {}

    public void windowClosed(WindowEvent e) {
        System.exit(0);
    }

    public void windowIconified(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowActivated(WindowEvent e) {}
    public void windowDecativated(WindowEvent e) {}
}
 

然而這有個缺點,實作介面的原則是您必須實作當中所定義的所有方法,即您對某些事g並不感興,您也必須實作一個沒有內容的I方法,代表您已E實作了介面中定的ҎQ然而有時,您並不知道介面中到底定義了幾個方法,或是知道也不知道Ҏ的確切名Ep參數Q即使您查了APIQ在E式中寫下一堆沒有實作內容的Ҏ也是很煩人的一件事?br>
WindowAdapter別預先實作了WindowListener介面Q每個方法中都是I的實作Q如下所C:
public abstract class WindowAdapter
                         implements WindowListener {
    public void windowOpened(WindowEvent e) {}
    public void windowClosing(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowActivated(WindowEvent e) {}
    public void windowDecativated(WindowEvent e) {}
}
 
可以J承WindowAdapter別Q並重新定義一些您所感興的事gQ如此一來,可以避開之前所提及的,直接實作 WindowListener介面的缺點,如下所C:
public class WindowEventHandler extends WindowAdapter {
    public void windowClosed(WindowEvent e) {
        System.exit(0);
    }
}
 

這就是Default Adapter模式Q它使用一個中介的Adapter別來將真正感興的事g實作別Q配接至事g處理介面Q上面的E式?UML 圖如下:
DefaultAdapter

上圖一般化QDefault Adapter模式的結構如下所C:
DefaultAdapter


]]>
Design Pattern: Proxy 模式Q二Q?/title><link>http://www.aygfsteel.com/jesson2005/articles/111171.html</link><dc:creator>张金?/dc:creator><author>张金?/author><pubDate>Tue, 17 Apr 2007 02:38:00 GMT</pubDate><guid>http://www.aygfsteel.com/jesson2005/articles/111171.html</guid><wfw:comment>http://www.aygfsteel.com/jesson2005/comments/111171.html</wfw:comment><comments>http://www.aygfsteel.com/jesson2005/articles/111171.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/jesson2005/comments/commentRss/111171.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/jesson2005/services/trackbacks/111171.html</trackback:ping><description><![CDATA[延續 <a >Proxy模式Q一Q?/a> 的議,來看看實現代理的兩種方式QStatic Proxy與Dynamic Proxy。嚴g說這是屬於模式的實現方式,不過藉由實例可以更瞭解Proxy模式的應用?br><br>先來看個例子,這個例子是a錄QlogQ動作,E式中很帔R要為某些動作或事件作下記錄,以便在事後檢視或是作為除錯時的資a,一個最單的例子如下: <br> <ul> <li>HelloSpeaker.java </li> </ul> <pre>import java.util.logging.*; <br><br>public class HelloSpeaker { <br> private Logger logger = <br> Logger.getLogger(this.getClass().getName()); <br><br> public void hello(String name) { <br> logger.log(Level.INFO, "hello method starts....");<br><br> System.out.println("Hello, " + name); <br><br> logger.log(Level.INFO, "hello method ends...."); <br> } <br>} </pre> <br>HelloSpeaker在執行hello()Ҏ時,您希望能a錄該方法已E執行及i束Q最單的作法就是如上在埯的前後加上記錄動作,然?Logger介入了HelloSpeaker中,a錄這個動作並不屬於HelloSpeakerQ這得HelloSpeaker增加了非業務上需要的邏輯在當中?br><br>x如果E式中這種a錄的動作到處都有需求,上面這種寫法勢必造成必須複製a錄動作的程式碼Q得維譯錄動作的困難度加大。如果不只有a錄動作Q有一些非物g本n聯K的相關動作也混入了物件之中(例如Ɗ限檢查、事務管理等{)Q會使得物g的負擔更形加重,甚至h了物件的聯KQ物件本w的聯K所佔的E式|或許遠小於這些與物件職責不盔R動作的程式碼?br><br>怎麼辦,用下面的Ҏ或許好一些,先定一個介面,然後實作該介面: <br> <ul> <li>IHello.java </li> </ul> <pre>public interface IHello { <br> public void hello(String name); <br>} <br></pre> <br> <ul> <li>HelloSpeaker.java </li> </ul> <pre>public class HelloSpeaker implements IHello { <br> public void hello(String name) { <br> System.out.println("Hello, " + name); <br> } <br>} <br></pre> <br>接下來實作一個代理物件HelloProxyQ?br> <ul> <li>HelloProxy.java </li> </ul> <pre>import java.util.logging.*; <br><br>public class <span id="wmqeeuq" class=createlink>HelloProxy</span> implements <span id="wmqeeuq" class=createlink>IHello</span> { <br> private Logger logger = <br> Logger.getLogger(this.getClass().getName()); <br> private <span id="wmqeeuq" class=createlink>IHello</span> helloObject; <br><br> public <span id="wmqeeuq" class=createlink>HelloProxy</span>(<span id="wmqeeuq" class=createlink>IHello</span> helloObject) { <br> this.helloObject = helloObject; <br> } <br><br> public void hello(String name) { <br> logger.log(Level.INFO, "hello method starts...."); <br><br> helloObject.hello(name); <br><br> logger.log(Level.INFO, "hello method ends...."); <br> } <br>}<br></pre> <br>埯時可以如此:<br> <div style="MARGIN-LEFT: 40px"><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">IHello helloProxy = new HelloProxy(new HelloSpeaker()); </span><br style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace"><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">helloProxy.hello("Justin");</span><br></div> <br>代理物gHelloProxy代理真正的HelloSpeaker來執行hello()Q並在其前後加上a錄的動作,這?HelloSpeaker在撰寫時不必介入a錄動作QHelloSpeaker可以心於它的職責?br><br>這是Static Proxy的基本範例,然而如您所看到的,代理物g的一個介面只服務gE類型的物gQ而且如果要代理的Ҏ很多Q勢必要為每個方法進行代理Q?Static Proxy在程式規模稍大時必定無法勝仅R?br><br>Java在JDK 1.3之後加入協助開發Dynamic Proxy功能的類別,我們不必為特定物g與方法撰寫特定的代理Q用Dynamic ProxyQ可以得一個handler服務於各個物Ӟ首先Q一個handler必須實現 java.lang.reflect.InvocationHandlerQ?<br> <ul> <li>LogHandler.java </li> </ul> <pre>import java.util.logging.*; <br>import java.lang.reflect.*; <br><br>public class LogHandler implements InvocationHandler { <br> private Logger logger = <br> Logger.getLogger(this.getClass().getName()); <br> private Object delegate; <br><br> public Object bind(Object delegate) { <br> this.delegate = delegate; <br> return Proxy.newProxyInstance(<br> delegate.getClass().getClassLoader(), <br> delegate.getClass().getInterfaces(), <br> this); <br> }<br> <br> public Object invoke(Object proxy, <br> Method method, <br> Object[] args) throws Throwable {<br> Object result = null; <br> try { <br> logger.log(Level.INFO, <br> "method starts..." + method); <br> result = method.invoke(delegate, args); <br> logger.log(Level.INFO, <br> "method ends..." + method); <br> } catch (Exception e){ <br> logger.log(Level.INFO, e.toString()); <br> } <br> return result; <br> } <br>} <br></pre> <br>InvocationHandler的invoke()Ҏ會傳入被代理物g的方法名Ep埯參數實際上要埯的方法交由method.invoke ()Q並在其前後加上a錄動作Qmethod.invoke()傛_的物件是實際Ҏ埯過後的回傳結果?<br><br>Dynamic Proxy必須宣告介面Q實作該介面Q例如: <br> <ul> <li>IHello.java </li> </ul> <pre>public interface IHello { <br> public void hello(String name); <br>} <br></pre> <br> <ul> <li>HelloSpeaker.java </li> </ul> <pre>public class HelloSpeaker implements IHello { <br> public void hello(String name) { <br> System.out.println("Hello, " + name); <br> } <br>} <br></pre> <br>java.lang.reflect.Proxy的newProxyInstance()依要代理的物件、介面與handler產生一個代理物Ӟ我們可以用下面的Ҏ來執行程式:<br> <div style="MARGIN-LEFT: 40px"><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">LogHandler logHandler = new LogHandler(); </span><br style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace"><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">IHello helloProxy = (IHello) logHandler.bind(</span><br style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace"><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">new HelloSpeaker()); </span><br style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace"><span style="FONT-WEIGHT: bold; FONT-FAMILY: Courier New,Courier,monospace">helloProxy.hello("Justin");</span><br></div> <br>LogHandler不在服務於特定物件與介面Q而HelloSpeaker也不用插入Q何有關於a錄的動作,它不用意識到a錄動作的存在?br> <img src ="http://www.aygfsteel.com/jesson2005/aggbug/111171.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/jesson2005/" target="_blank">张金?/a> 2007-04-17 10:38 <a href="http://www.aygfsteel.com/jesson2005/articles/111171.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Design Pattern: Facade 模式http://www.aygfsteel.com/jesson2005/articles/111173.html张金?/dc:creator>张金?/author>Tue, 17 Apr 2007 02:38:00 GMThttp://www.aygfsteel.com/jesson2005/articles/111173.htmlhttp://www.aygfsteel.com/jesson2005/comments/111173.htmlhttp://www.aygfsteel.com/jesson2005/articles/111173.html#Feedback0http://www.aygfsteel.com/jesson2005/comments/commentRss/111173.htmlhttp://www.aygfsteel.com/jesson2005/services/trackbacks/111173.html
當您拿到一些現成的元gQ並打算在您的應用程式中使用它們的話,您不應該直接這些元g耦合x的應用程式上Q例如:
Facade

上面的作法會讓您的應用程式直接與多個元件耦合Q這種作法不但與元件的依賴度高Q日後要修改應用E式本nQ或是更換掉依賴的元仉有困難?br>
您應該定一個Facade介面Q在當中定義好商務邏輯,例如寄送附件檔案的ҎQmethodQ,然後在一個實N中,i合您手邊的元gQ光成您所希望的商務行為,例如Q?br>Facade

如上圖所C的Q您的應用程式本w將不直接依賴於您的元gQ而是依賴一個介面,當您惌更改某個商務行為的實作時,只要修改實現的類可以了Q應用程式本w不用作M修改?br>
Facade模式的結構如下:
Facade

Facade模式p了各個元件之間的合作行為Q以及元件本w的操作與設定細Q固而必失去了一些直接操作元件的方便性,所以對於喜歡追求與操作細節的程式設ah員而言Q不會很喜歡透過Facade來操作背後的元gQ所以您的Facade介面a計Q通常要在元g依賴性及元g的支接操作性之間作個^衡?br>


]]>
Design Pattern: Proxy 模式Q一Q?/title><link>http://www.aygfsteel.com/jesson2005/articles/111170.html</link><dc:creator>张金?/dc:creator><author>张金?/author><pubDate>Tue, 17 Apr 2007 02:37:00 GMT</pubDate><guid>http://www.aygfsteel.com/jesson2005/articles/111170.html</guid><wfw:comment>http://www.aygfsteel.com/jesson2005/comments/111170.html</wfw:comment><comments>http://www.aygfsteel.com/jesson2005/articles/111170.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/jesson2005/comments/commentRss/111170.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/jesson2005/services/trackbacks/111170.html</trackback:ping><description><![CDATA[?<a >Gof 的書</a>中對Proxy模式的目的定為Q為其它的物件提供一E代理,以控制對這個物件的a問。由這句話所延Z的意思是Q根據您的目的不同,您的代理物g負有不同的責QQ因為產生多E不同的代理情況?br><br>Ҏ不同的代理目的,而有不同的代理情況,在Gof中所舉的一個例子是Virtual ProxyQ當中舉一個文檔中內嵌圖片的例子,假設您的圖片是在文檔分頁的後面,一開始您並不用直接載入圖片Q而用一個虛代理物gQ代替圖片被載入Q以求開啟一個文檔的時候,速度能夠加快。當您捲動文檔至該顯C圖片的頁數時,這時再載入圖片?br> <div style="TEXT-ALIGN: center"><img title=Proxy style="WIDTH: 369px; HEIGHT: 246px" alt=Proxy src="http://caterpillar.onlyfun.net/Gossip/DesignPattern/images/proxy-1.jpg"><br></div> <br>如上圖所C,當文檔被開啟時,ImageProxy物g代理Image物g被載入,在還沒捲動至圖片示處時Q也是還沒有調?ImageProxy的draw()時,圖片並不會被載入Q因而可以加速文檔的開啟與節省記憉的用;如果需要顯C圖片了QImageProxy?draw()會被調用Q而這時才真正創建Image物gQ以從硬中載入圖片?br><br>Proxy模式?UML i構圖如下所C:<br> <div style="TEXT-ALIGN: center"><img title=Proxy style="WIDTH: 330px; HEIGHT: 237px" alt=Proxy src="http://caterpillar.onlyfun.net/Gossip/DesignPattern/images/proxy-2.jpg"><br></div> <br>在調用RealSubject的request()之前QProxy物g也許會有一些預先處理的操作Q就假設我們組J為preOperation()?postOperation()好了Q當客戶Proxy發出request()請求後,一個可能的時序圖如下所C:<br> <div style="TEXT-ALIGN: center"><img title=Proxy style="WIDTH: 321px; HEIGHT: 350px" alt=Proxy src="http://caterpillar.onlyfun.net/Gossip/DesignPattern/images/proxy-3.jpg"><br></div> <br>您的preOperation()與postOperation()正決定了Proxy模式使用gE情況,例如一個Remote Proxy的情況,可以Z個遠端真實物件提供一個局部代表;Protection Proxy控制物件的a問Q您可以使用它來作不同級別、權限的存取控制QCache ProxyZ個物件提供臨時的儲存Q得許多客戶端都能直接存取它,而不用對真實物g直接要求Q只有在必要的時候更新這個臨時物Ӟ或是讓客戶直接存取真實物件? <img src ="http://www.aygfsteel.com/jesson2005/aggbug/111170.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/jesson2005/" target="_blank">张金?/a> 2007-04-17 10:37 <a href="http://www.aygfsteel.com/jesson2005/articles/111170.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">᯹</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ˮ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ĵ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ļ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ӱ</a>| <a href="http://" target="_blank">Ĭ</a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank">IJ</a>| <a href="http://" target="_blank">ǰ</a>| <a href="http://" target="_blank">ˮ</a>| <a href="http://" target="_blank">ϴ</a>| <a href="http://" target="_blank">°Ͷ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">̨</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ˮ</a>| <a href="http://" target="_blank">˫</a>| <a href="http://" target="_blank">ʯɽ</a>| <a href="http://" target="_blank">ʤ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">¹</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ϣ</a>| <a href="http://" target="_blank">ϳ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>