工廠方法是針對每一種產品提供一個工廠類。通過不同的工廠實例來創建不同的產品實例。在同一等級結構中,支持增加任意產品。
現在有一個具體的案例:
設計一個程序來讀取多種不同類型的圖片格式,針對每一種圖片格式都設計個圖片讀取器( Imagereader),如GIF圖片讀取器( Gifreader)用於讀取GIF格式的圖片、JPG圖片讀取器( Jpg Reader)用於讀取JPG格式的圖片。圖片讀取器對象通過圖片讀取器工廠 ImageReaderFactory來創建, ImageReaderFactory是一個抽象類,用於定義創建圖片讀取器的工廠方法,其子類 Gifreaderfactory和 Jpg Readerfactory用於創建具體的圖片讀取器對象。
畫出符合工廠方法模式的設計類圖——(此設計不太好,client.java對四個類的依賴讓工廠模式失去了意義。建議使用xml進行圖像文件配置的設置。)
在這個類圖中,所有特定的Reader對象都由其對應的Factory對象進行create操作。而在客戶端中只需要調用Factory來根據需要生成不同的Reader。這樣設計以後,假設後期想要添加新的格式讀取,就再增加一個Reader類和相應的Factory類,少量修改client即可,而無需像傳統結構一樣修改已經部署的源代碼,通過這種設計較好地滿足了軟件工程中“對拓展開放,對修改關閉”的概念。
附上該設計實例的demo便於理解:
Client.java
public class client {
public static void main(String[] args) {
System.out.println("*********程序啓動**********");
System.out.println("想要讀取一個圖像文件,格式爲:");
System.out.println("A.jpg B.gif");
Scanner s = new Scanner(System.in);
String input = s.nextLine();
switch (input) {
case "A":
JpgReader jReader = new JpgReaderFactory().createImageReader();
jReader.ReaderImage();
break;
case "B":
GifReader gReader = new GifReaderFactory().createImageReader();
gReader.ReaderImage();
break;
default:
System.out.println("錯誤,選擇A或B的格式。");
break;
}
}
}
ImageReader.java
public abstract class ImageReader {
public abstract void ReaderImage();
}
GifReader.java
public class GifReader extends ImageReader {
@Override
public void ReaderImage() {
System.out.println("我是"+this.getClass()+",我負責讀取GIF格式的文件。");
}
}
JpgReader.java
public class JpgReader extends ImageReader {
@Override
public void ReaderImage() {
System.out.println("我是"+this.getClass()+",我負責讀取JPG格式的文件。");
}
}
ImageReaderFactory.java
public abstract class ImageReaderFactory {
public abstract ImageReader createImageReader();
}
GifReaderFactory.java
public class GifReaderFactory extends ImageReaderFactory {
@Override
public GifReader createImageReader() {
return new GifReader();
}
}
JpgReaderFactory.java
public class JpgReaderFactory extends ImageReaderFactory {
@Override
public JpgReader createImageReader() {
return new JpgReader();
}
}
運行後的“客戶端”效果如下(爲了使‘工廠’的概念更明顯,在相應的Reader中使用getClass方法返回了生成的類名)