Android 原始碼設計模式解析與實戰 讀書筆記 5 工廠方法模式

b10l07發表於2018-03-19

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

1. 工廠方法模式介紹

工廠方法模式(Factory Pattern),是建立型設計模式之一。工廠方法模式是一種結構簡單的模式,在我們平時開發中應用廣泛,如 Android 中的 Activity 的各個生命週期方法,以 onCreate 方法為例,它就可以看作是一個工廠方法,我們在其中可以構造我們的 View 並通過 setContentView 方法返回給 framework 處理。

2. 工廠方法模式的定義

定義一個用於建立物件的介面,讓子類決定例項化哪個類。

3. 工廠方法模式的使用場景

在任何需要生成複雜物件的地方,都可以使用工廠方法模式。複雜物件適合使用工廠方法模式,用 new 就可以完成建立的物件無需使用工廠方法模式。

4. 工廠方法模式的通用模式程式碼

簡單的例項:

public abstract class Product {
    public abstract void method();
}


public class ConcreteProductA extends Product {
    @Override
    public void method() {
        System.out.println("我是具體產品 A");
    }
}


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


public abstract class Factory {
    public abstract Product createProduct();
}


public class ConcreteFactoryA extends Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

對例項的測試:

public class Client {
    public static void main() {
        Factory factoryA = new ConcreteFactoryA();
        Product productA = factoryA.createProduct();
        productA.method();
    }
}

有時候也可以利用反射的方式更簡潔地來生產具體產品物件,此時,需要在工廠方法的引數列表中傳入一個 Class 類來決定是哪一個產品類:

public abstract class Factory {
    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 p = null;
        try {
            p = (Product) Class.forName(clz.getName()).newInstance();
        } catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return (T) p;
    }
}

對例項的測試:

public class LearnJava {

    public static void main(String[] args) {
        Factory factory = new ConcreteFactory();
        Product product = factory.createProduct(ConcreteProductA.class);
        product.method();
        product = factory.createProduct(ConcreteProductB.class);
        product.method();
    }
}

當然,我們也可以為每個產品建立一個具體的工廠(多工廠模式):

public class ConcreteFactoryA extends Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

public class ConcreteFactoryB extends Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

如果確定工廠類只有一個,那麼也可以簡化掉抽象類,我們只需要將抽象的工廠方法改為靜態方法即可:

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

5. 工廠方法模式實戰

Android 的資料持久化有多種方式,但是,對資料的操作方法無非就是增、刪、改、查,我們可以將每一種資料操作的方式作為一個產品類,在抽象產品類中定義操作的方法:

public abstract class IOHandler {
    public abstract void add(String id, String name);
    public abstract void remove(String id);
    public abstract void update(String id, String name);
    public abstract String query(String id);
}

對於每一種持久化方式我們都定義一個具體的 IO 處理類,這裡就定義一種作為示例:

public class FileHandler extends IOHandler {
    @Override
    public void add(String id, String name) {

    }

    @Override
    public void remove(String id) {

    }

    @Override
    public void update(String id, String name) {

    }

    @Override
    public String query(String id) {
        return "File Handler";
    }
}

工廠方法:

public class IOFactory {
    public static <T extends IOHandler> T getIOHandler(Class<T> clz) {
        IOHandler handler = null;
        try {
            handler = (IOHandler) Class.forName(clz.getName()).newInstance();
        } catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) {
            e.printStackTrace();
        }

        return (T) handler;
    }
}

測試:

public class LearnJava {

    public static void main(String[] args) {
        IOHandler handler = IOFactory.getIOHandler(FileHandler.class);
        System.out.println("current handler is: " + handler.query("who care"));
    }
}

總結

總的來說,工廠方法模式是一個很好的設計模式。但是缺點也是難以避免,每次我們為工廠方法模式新增新的產品時就要編寫一個新的產品類,同時還要引入抽象層,這必然會導致類結構的複雜化,所以,在某些情況比較簡單時,是否要使用工廠模式,需要設計者權衡利弊。

相關文章