搜尋

首頁  >  問答  >  主體

java - 抽象工厂模式支持什么样的业务背景

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();
    }
}

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

黄舟黄舟2785 天前699

全部回覆(1)我來回復

  • 大家讲道理

    大家讲道理2017-04-18 09:29:40

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

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

    第 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: 為了顯得不會太囉嗦,所以工廠方法的實現,這裡採用內部類別來完成。

    回覆
    0
  • 取消回覆