java設計模式——建立型之工廠三兄弟(1)
自大學課程初識設計模式以來,就越發覺得有必要系統學習一下設計模式。
剛好在實習前準備期間課比較少,抽出一點時間整理一下記一些筆記,複製貼上比較多。
筆記比較適合學習過設計模式的同學。
Simple Factory Pattern(簡單工廠模式)
簡單工廠模式的適用範圍
(1) 工廠類負責建立的物件比較少,由於建立的物件較少,不會造成工廠方法中的業務邏輯太過複雜。
反映到程式碼上就是Factory類邏輯要簡單就要建立物件少
(2) 客戶端只知道傳入工廠類的引數,對於如何建立物件並不關心。
顧客不應該知道產品是如何做的,只需要知道自己需要的產品的名字。
簡單工廠模式如何實現
角色
Factory(工廠角色)
工廠角色即工廠類,它是簡單工廠模式的核心,負責實現建立所有產品例項的內部邏輯;工廠類可以被外界直接呼叫,建立所需的產品物件;在工廠類中提供了靜態的工廠方法 factoryMethod(),它的返回型別為抽象產品型別 Product。
Product(抽象產品角色)
它是工廠類所建立的所有物件的父類,封裝了各種產品物件的公有方法,它的引入將提高系統的靈活性,使得在工廠類中只需定義一個通用的工廠方法,因為所有建立的具體產品物件都是其子類物件。
ConcreteProduct(具體產品角色)
它是簡單工廠模式的建立目標,所有被建立的物件都充當這個角色的某個具體類的例項。每一個具體產品角色都繼承了抽象產品角色,需要實現在抽象產品中宣告的抽象方法。
類圖
可以看到類圖中除了上述,在Factory類中還有一個方法用於根據客戶端引數返回產品物件,因此客戶端只需要提供引數而不使用new XXX來創造產品。
當然Factory類有時也可以與Product類結合成一個類
簡單工廠模式的優缺點
主要優點
(1) 工廠類包含必要的判斷邏輯,可以決定在什麼時候建立哪一個產品類的例項,客戶端可以免除直接建立產品物件的職責,而僅僅“消費”產品,簡單工廠模式實現了物件建立和使用的分離。
(2) 客戶端無須知道所建立的具體產品類的類名,只需要知道具體產品類所對應的引數即可,對於一些複雜的類名,通過簡單工廠模式可以在一定程度減少使用者的記憶量。
(3) 通過引入配置檔案,可以在不修改任何客戶端程式碼的情況下更換和增加新的具體產品類,在一定程度上提高了系統的靈活性。
主要缺點
(1) 由於工廠類集中了所有產品的建立邏輯,職責過重,一旦不能正常工作,整個系統都要受到影響。
(2) 使用簡單工廠模式勢必會增加系統中類的個數(引入了新的工廠類),增加了系統的複雜度和理解難度。
(3) 系統擴充套件困難,一旦新增新產品就不得不修改工廠邏輯,在產品型別較多時,有可能造成工廠邏輯過於複雜,不利於系統的擴充套件和維護。
(4) 簡單工廠模式由於使用了靜態工廠方法,造成工廠角色無法形成基於繼承的等級結構。(這一點其實我不是很懂,有懂的朋友教我一下嗎?)
練習
題目
使用簡單工廠模式設計一個可以建立不同幾何形狀(如圓形、方形和三角形等)的繪圖工具,每個幾何圖形都具有繪製 draw() 和擦除 erase() 兩個方法,要求在繪製不支援的幾何圖形時,提示一個 UnSupportedShapeException。
實現程式碼
抽象產品:Shape.java
package com.joy;
public abstract class Shape {
public abstract void draw();
public abstract void erase();
}
具體產品:Circle.java
package com.joy;
public class Circle extends Shape{
@Override
public void draw() {
System.out.println("繪製圓形");
}
@Override
public void erase() {
System.out.println("擦除圓形");
}
}
具體產品:Rectangle.java
package com.joy;
public class Rectangle extends Shape{
@Override
public void draw() {
System.out.println("繪製長方形");
}
@Override
public void erase() {
System.out.println("擦除長方形");
}
}
具體產品:Triangle.java
package com.joy;
public class Triangle extends Shape{
@Override
public void draw() {
System.out.println("繪製三角形");
}
@Override
public void erase() {
System.out.println("擦除三角形");
}
}
工廠類:Factory.java
這個地方有一點不好,為了圖方便把UnSupportedShapeException類寫在這個方法裡了,應該獨立分開的。
package com.joy;
public class Factory {
public static Shape getShape(String shapeName) throws UnSupportedShapeException{
if(shapeName.equals("Circle"))
return new Circle();
else if(shapeName.equals("Rectangle"))
return new Rectangle();
else if(shapeName.equals("Triangle"))
return new Triangle();
else
throw new UnSupportedShapeException();
}
}
class UnSupportedShapeException extends Exception{
}
客戶端:SimpleFactoryDemo.java
package com.joy;
public class SimpleFactoryDemo {
public static void main(String[] args) {
Factory f = new Factory();
try {
System.out.println("*獲取指定形狀");
Shape shape = f.getShape("Circle");//圓形
System.out.println("*控制繪製");
shape.draw();
System.out.println("*控制擦除");
shape.erase();
System.out.println("*獲取指定形狀");
Shape shape1 = f.getShape("Square");//正方形,沒有該形狀
} catch (UnSupportedShapeException e) {
e.printStackTrace();
}
}
}
執行結果
總結
簡單工廠雖然把產品都獨立出來,將建立和呼叫分開了,但是Factory方法變得複雜和不靈活,應該改進。