java - 抽象工厂模式支持什么样的业务背景
黄舟
黄舟 2017-04-18 09:27:40
0
1
696
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: 为了显得不会太啰嗦,所以工厂方法的实现,这里采用内部类来完成。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板