java - 抽象工厂模式支持什么样的业务背景
黄舟
黄舟 2017-04-18 09:27:40
0
1
725
package GOF;

interface Create {

    public void create();
}

class A implements Create {

    @Override
    public void create() {
        System.out.println("A");
    }
}

class B implements Create {

    @Override
    public void create() {
        System.out.println("B");
    }
}

interface Produce {

    public Create produce();
}

class C implements Produce {

    @Override
    public Create produce() {
        return new A();
    }
}

class D implements Produce {

    @Override
    public Create produce() {
        return new B();
    }
}

public class AbstractFactory {

    public static void main(String[] args) {
        Produce produce = new C();
        Create create = produce.produce();
        create.create();
    }
}

如上图所示代码,是抽象工厂模式的实例。请问在实际的业务场景中如何使用?有什么优点。

黄舟
黄舟

人生最曼妙的风景,竟是内心的淡定与从容!

全部回覆(1)
大家讲道理

覺得你問的這個問題很有意義,很多人對設計模式都不能靈活的應用

下面我從分析問題的角度,談談為什麼要用工廠類的設計模式

第 1 個問題:我們經常一些功能類似的類,所以我們的思路是對進行抽象,使用接口暴露公共的方法,使用抽象類來提供公共的實現。

public interface IProduct {
    void print(); // 这是要暴露的方法
}

public abstract class AbstractProduct implements IProduct {
    protected void printBefore(){
        System.out.println("before print"); // 这里所公共的实现
    }
}

public class AProduct extends AbstractProduct {
    private String name;
    public AProduct(String name){ 
        this.name = name;
    }
    @Override
    public void print() {
        this.printBefore();
        System.out.println("print A >>>"+name);
    }
}

public class BProduct extends AbstractProduct {
    private String name;
    public BProduct(String name){ 
        this.name = name;
    }
    @Override
    public void print() {
        this.printBefore();
        System.out.println("print B >>>"+name);
    }
}

第 2 個問題:這些功能類似的類別的實例化變成了一個問題,每個類別的建構方法參數還不一樣,每次 new 物件都很麻煩,封裝成簡單工廠模式

public class SimpleFactory {
    public static IProduct getProduct(String name){
        if("A".equals(name)){
            return new AProduct(name);
        }else if("B".equals(name)){
            return new BProduct(name);
        }else{
            throw new IllegalArgumentException();
        }
    }
}

第3 個問題:簡單工廠模式不利於拓展,違背了開閉原則,每次添加一個類,都要修改工廠類(如果是工廠類和業務類是兩個小伙伴分開寫的,那不是要花很多時間來溝通...),所以就有工廠方法模式,其原理就是對簡單工廠也進行抽象。

public interface IFactory {
    IProduct getProduct();
}

public class AFactory implements IFactory {
    @Override
    public IProduct getProduct() {
        return new AProduct(AProduct.class.getName());
    }
}

public class BFactory implements IFactory {
    @Override
    public IProduct getProduct() {
        return new BProduct(BProduct.class.getName());
    }
}

第 4 個問題:突然發現有些糟糕了,因為程式碼變得很多了,因為功能類似的產品我們進行 3 層抽象,針對每個產品我們還抽像出了 2 層的工廠類別。但是我們在某個具體的業務場景中,不單單是只實例化一個類別啊。舉一個例子,在遊戲中,我們要一個戰士配裝備,首先我們需要配一把槍械(槍械有很多,步槍,狙擊槍等,使用問題1 進行抽象),但是配了槍械之後,我們還需要配子彈啊(繼續用問題1 的方法進行抽象),好了,現在可以抽像出2 層的工廠類了,針對現在的情況我們是不是可以讓一個工廠既生產槍械,又生產子彈呢? 這就是抽象工廠模式。簡單來說,可以把有一些有聯繫或相似的產品,放到一個工廠去生產,沒有必要單獨再開一個工廠了

另外修正一下,你貼的程式碼是工廠方法模式,不是抽象工廠模式。


看到題主還沒採納我的答案,我就多說幾句吧,給一個具體的應用案例。

我們都知道 Java 的泛型是採用型別擦除來實現的(在 javac 編譯過程的中把泛型去掉,加上強制型別轉換)。所以我們不能直接 new T()來實例化一個物件。其實可以用工廠方法模式設計模式來解決。

假設我們有一個類,裡面要用到了泛型的實例化。

public class Foo<T>(){
    private T t;
    public Foo(){
       t = new T(); // 这个代码是有问题的,我们使用工厂设计模式进行改进
    }
}

我們給出工廠介面如下:

public interface IFactory<T>(){
    T create();
}

進而我們可以採用以下的方法來改進

public class Foo<T>(){
    private T t;
    public <F extends IFactory<T>> Foo(F factory){
        // t = new T(); 
        factory.create();       
    }
}

這個時候,我們可以用如下的方式實例化 Foo

new Foo(new Ifactory<Integer>(){
    Integer create(){
        return new Integer(0);
    }
});

new Foo(new Ifactory<String>(){
    String create(){
        return "Hello";
    }
});

ps: 為了顯得不會太囉嗦,所以工廠方法的實現,這裡採用內部類別來完成。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板