【问题标题】:Factory Pattern and dependencies [duplicate]工厂模式和依赖项[重复]
【发布时间】:2018-02-16 12:24:47
【问题描述】:

工厂方法用于避免违反开闭原则。 而不是通过继承创建对象:

Product myProd = new ConcreteProduct1; // concreteProduct extends abstract product
myProd.doSomething();

我们使用工厂“接口”与相关的具体工厂(实现工厂并覆盖其方法的类):

Factory myFact = new ConcreteFact1; // (2)
Product myProd = myFact.createProd();   // (1)
myProd.doSomething(); // (1)

我读过很多关于工厂方法的文章;我明白,使用工厂方法,可以排除开闭原则的缺陷。但我还是不明白:

  1. 使用这种设计模式,我们仍然依赖于类 Product (myProd) (1)
  2. 此外.. 我们与 Concrete-Factories 有依赖关系(客户需要实例化一个特定的想要的具体工厂,并且客户必须知道女巫之一)(2)

感谢您的澄清。

【问题讨论】:

  • 您以错误的方式使用工厂。工厂通常有提供“产品”的静态方法。但是在 (2) 处的代码中,您使用 myFact 甚至没有使用它。
  • 我做错了,代码更新了。

标签: java oop design-patterns factory-pattern


【解决方案1】:
  1. 我们确实对Product有依赖,但关键是要消除对ConcreteProduct的依赖。

  2. 不,我们不依赖ConcreteFactory,因为我们将工厂作为参数传递。

    class MassProduction {
        ProductFactory factory;
        public MyClass(ProductFactory fact) {
           factory = fac;
        }
        public List<Product> produce(int amount) {
            ArrayList<Product> result = new ArrayList<>(amount);
            for (int i = 0; i < amount; i++) { 
                result.add(factory.createProduct());
            }
            return result;
        }
    }
    

我们绝不会依赖ConcreteProductConcreteFactory

【讨论】:

  • 谢谢你这个奇妙的例子,我问你最后一个澄清:调用 MassProduction.MyClass(fact) 的客户必须了解 ConcreteFactories(女巫事实)。有办法避免这种情况吗?坦克你
  • @Marco 嗯,是的,当然,最终确实有人必须通过一个具体的课程,但只是在最后。关键是,该客户将能够使用MassProduction 设施,而MassProduction 不知道客户的Product
  • 之前我有:Factory myFact = new ConcreteFact1 现在我有:Factory myfactory = new MassProduct; myfactory.myClass(new ConcreteFactory1());这对我来说真是个谜..
【解决方案2】:

您可能并不完全需要使用整个概念。

这是一个用例:

// define the interfaces
public interface Product {}
public interface ProductFactory {
    public Product createProduct();
}
// create some implementors
public class Sweatshirt implements Product {
    static final ProductFactory FACTORY = new ProductFactory() {
        public Product createProduct() {
            return new Sweatshirt();
        }
    }
}
public class Pants implements Product {
    static final ProductFactory FACTORY = new ProductFactory() {
        public Product createProduct() {
            return new Pants();
        }
    }
}
public class Hat implements Product {
    static final ProductFactory FACTORY = new ProductFactory() {
        public Product createProduct() {
            return new Hat();
        }
    }
}

// create a client class
class Stock {
    private List<? extends Product> stock = new ArrayList<>();
    public void add(int amount, ProductFactory fac) {
        for (int i = 0; i < amount; i++) {
            stock.add(fac.createProduct());
        }
    }
    public void printAll() {
        stock.forEach(p -> System.out.println(p.getClass()));
    }
}

// driver class that allows the user to enter amounts and product type
// and adds them to the stock until any entry is invalid
class InventoryManagement {
    public static void main(String[] args) {
        Stock stock = new Stock();
        try (Scanner sc = new Scanner(System.in)) {
            while (true) {
                // read amount from console input
                int amount = sc.nextInt();
                // read type from console input
                String value = sc.next();
                ProductFactory factory = null;
                switch(value) {
                    case "s":
                         factory = Sweatshirt.FACTORY;
                         break;
                    case "p":
                         factory = Pants.FACTORY;
                         break;
                    case "h":
                         factory = Hat.FACTORY;
                         break;
                 }
                 if (factory != null) {
                     stock.add(amount, factory);
                 } else {
                     break;
                 }
            }
        } catch (Exception e) {} 
        stock.printAll();
    }
}

如您所见,客户端类 (Stock) 没有对任何具体的ProductFactory 的任何引用,但它使用给定的Factorys 来创建Products。它是连接两者的驱动程序类(客户端类Stock 和具体产品)。

【讨论】:

  • 谢谢你的帮助,但我还是不明白:现在情况又回来了。在静态主中,我们再次直接依赖于具体产品。 (我们需要导入相关类)
  • static main 是您的主程序...您最终将必须拥有实际产品,而您的 main 是最后一个可能的时间点。我想您可以一般地构建产品工厂,例如从数据库加载而无需引用实际类,但如何做到这一点是一个不同的问题。
  • 我试图解释在 Stock 类中使用工厂依赖于具体产品,就像在第一种情况下(多态性)一样。有什么区别?
  • 您不依赖Stock 中的具体产品,只依赖于主要产品。您的Stock 可用于任何类型的产品,只要您有工厂即可。这意味着您可以通过为它们提供工厂来将您的 Stock 类重用于另一个程序,并使用另一个主要方法添加不同的产品(例如 YoghurtIceCreamJello)。
  • 好的,在 main.. 但是我们开始使用工厂方法是因为“创建对象的问题,而不必指定将要创建的对象的确切类”(维基百科)。现在,在 main 中,我们必须再次指定(调用、导入、使用..)它们......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多