工廠方法模式——應用最廣泛

(《設計模式解析與實戰》讀書筆記)

一、定義
定義一個用於創建對象的接口,讓子類決定實例化哪個類。它是創建型設計模式之一。
二、使用場景
在任何需要生成複雜對象的地方,都可以使用工廠方法模式。複雜對象適合使用工廠模式,用new就可以完成創建的對象無需使用工廠模式。
三、工廠方法模式的通用模式代碼

/**
 * 抽象產品類
 */
public abstract class Product {
    /**
     * 產品類的抽象方法由具體的產品類去實現
     */
    public abstract void method();
}
/**
 * 具體產品類A
 */
public class ConcreteProductA extends Product{

    @Override
    public void method() {
        System.out.println("我是具體的產品A");
    }
}
/**
 * 具體產品類B
 */
public class ConcreteProductB extends Product{

    @Override
    public void method() {
        System.out.println("我是具體的產品B");
    }
}
/**
 * 抽象工廠類
 */
public abstract class Factory {
    /**
     * 抽象工廠方法具體生產什麼由子類去實現
     * 
     * @return 具體的產品對象
     */
    public abstract Product createProduct();
}
/**
 * 具體工廠類
 */
public class ConcreteFactory extends Factory {

    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }

}
/**
 * 客戶類
 */
public class Client {
    public static void main(String[] args) {
        Factory factory = new ConcreteFactory();
        Product product = factory.createProduct();
        product.method();
    }
}

運行:
這裏寫圖片描述
主要分爲四大模塊:
(1)抽象工廠,核心;
(2)具體工廠,具體的業務邏輯;
(3)抽象產品,所創建的產品的父類;
(4)具體產品,實現抽象產品的某個具體產品的對象。

當然可以利用反射的方式更簡潔的來生產具體產品對象:

/**
 * 抽象工廠類
 */
public abstract class Factory {
    /**
     * 抽象工廠方法具體生產什麼由子類去實現
     * 
     * @param clz
     *            產品對象類型
     * @return 具體的產品對象
     */
    public abstract <T extends Product> T createProduct(Class<T> clz);
}

/**
 * 具體工廠類
 */
public class ConcreteFactory extends Factory {

    @Override
    public <T extends Product> T createProduct(Class<T> clz) {
        Product product = null;
        try {
            product = (Product) Class.forName(clz.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) product;
    }
}

/**
 * 客戶類
 */
public class Client {
    public static void main(String[] args) {
        Factory factory = new ConcreteFactory();
        Product product = factory.createProduct(ConcreteProductA.class);
        product.method();
    }
}

這種方法簡潔、動態,不需要爲每一個產品都定義一個具體的工廠。
如果工廠類只有一個,那麼就可以簡化掉抽象類,只需要將工廠方法改爲靜態方法。

/**
 * 簡單工廠模式或靜態工廠模式
 */
public class EasyFactory {
    public static Product createProduct() {
        return new ConcreteProductA();
    }
}

四、實例
以數據存儲爲例,將每一種數據操作的方式作爲一個產品類,在抽象產品類中定義操作的方法:

/**
 * 抽象數據存儲類
 */
public abstract class IOHandler {
    /**
     * 添加一條個人信息
     * 
     * @param id
     *            身份證號碼
     * @param name
     *            名字
     */
    public abstract void add(String id, String name);

    /**
     * 刪除一條個人信息
     * 
     * @param id
     */
    public abstract void remove(String id);

    /**
     * 更新一條個人信息
     * 
     * @param id
     *            身份證號碼
     * @param name
     *            名字
     */
    public abstract void update(String id, String name);

    /**
     * 查詢身份證對應的人名
     * 
     * @param id
     */
    public abstract String query(String id);
}

/**
 * 文件存儲
 */
public class FileHandler extends IOHandler {

    @Override
    public void add(String id, String name) {
        // TODO 文件存儲代碼
    }

    @Override
    public void remove(String id) {
        // TODO 文件刪除代碼
    }

    @Override
    public void update(String id, String name) {
        // TODO 文件修改代碼
    }

    @Override
    public String query(String id) {
        // TODO 文件查詢代碼
        return "文件存儲";
    }
}

/**
 * XML文件存儲
 */
public class XMLHandler extends IOHandler{

    @Override
    public void add(String id, String name) {
        // TODO 業務處理

    }

    @Override
    public void remove(String id) {
        // TODO Auto-generated method stub

    }

    @Override
    public void update(String id, String name) {
        // TODO Auto-generated method stub

    }

    @Override
    public String query(String id) {
        // TODO Auto-generated method stub
        return "XML文件存儲";
    }
}

/**
 * SQLite數據庫存儲
 */
public class DBHandler extends IOHandler {

    @Override
    public void add(String id, String name) {
        // TODO 業務處理

    }

    @Override
    public void remove(String id) {
        // TODO Auto-generated method stub

    }

    @Override
    public void update(String id, String name) {
        // TODO Auto-generated method stub

    }

    @Override
    public String query(String id) {
        // TODO Auto-generated method stub
        return "SQLite數據庫存儲";
    }
}

/**
 * 數據存儲工廠類
 */
public class IOFactory {
    /**
     * 獲取IO處理者
     * 
     * @param clz
     *            處理類的類型
     * @return IOHandler對象
     */
    public static <T extends IOHandler> T getIOHandler(Class<T> clz) {
        IOHandler handler = null;
        try {
            handler = (IOHandler) Class.forName(clz.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) handler;
    }
}
public class MainActivity extends Activity {

    private IOHandler handler;
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = (TextView) findViewById(R.id.tv_text);
    }

    public void onClick(View v) {
        switch (v.getId()) {
        // 查詢普通文本數據
        case R.id.btn_file:
            handler = IOFactory.getIOHandler(FileHandler.class);
            mTextView.setText(handler.query("123"));
            break;
        // 查詢XML文件數據
        case R.id.btn_xml:
            handler = IOFactory.getIOHandler(XMLHandler.class);
            mTextView.setText(handler.query("123"));
            break;
        // 查詢數據庫數據
        case R.id.btn_db:
            handler = IOFactory.getIOHandler(DBHandler.class);
            mTextView.setText(handler.query("123"));
            break;
        case R.id.btn_default:
            mTextView.setText("點擊按鈕查詢結果");
            break;

        default:
            break;
        }
    }
}

演示結果:
這裏寫圖片描述
五、優缺點
優點:
(1)降低了對象之間的耦合度;
(2)將實例化的任務交由子類去完成,有非常好的擴展性;
(3)結構簡單,邏輯基本類似。
缺點:
每次爲工廠方法模式添加新的產品時就要編寫一個新的產品類,同時還要引入抽象層,這會導致類結構的複雜化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章