【问题标题】:Small but realistic use case for factory pattern?工厂模式的小而现实的用例?
【发布时间】:2020-04-06 17:54:08
【问题描述】:

我了解工厂模式如何工作的 Java 和 C++ 代码示例,尽管我从未使用 Java 编写过代码,也有近 2 年没有使用 C++ 编写过代码。我只需要理解这个概念就可以遵循一些 API 文档。

我无法理解的是用例。大多数解释说,如果您使用工厂方法根据其参数之一的值创建派生类的对象,则可以更轻松地扩展派生类的数量。在高层次上,我理解这些词,但我还没有找到一个代码示例说明工厂的缺失是一个问题。我能找到的在代码级别显示问题的唯一尝试是here。

示例存在许多问题,如this question 的 cmets 中所述。但是,我想把它们放在一边,专注于工厂要解决的问题。

引用的代码分为 (i) Vehicle 基类的库代码和 (ii) 用于实例化表示(例如)TwoWheeler 或 ThreeWheeler 的特定 Vehicle 子类的客户端代码。问题的解决方案是,如果您将新的子类添加到现有子类的集合中,则无需重新调整任何客户端代码。但是Client 类的例子太琐碎了,看不出问题所在。确切的 Vehicle 子类规范被硬编码到 Client 类定义中。任何使用 Client 创建对象的地方,都可以轻松创建指定子类的对象。

我知道示例必须简单,以便人们可以看穿代码和语法,并理解推理。但所描述的逻辑似乎仍然集中在工厂的机制上,并没有描述对工厂的真正需求。

谁能指出一个在线代码级示例,显示对工厂的实际需求?

我仍在处理我保存的一系列链接,但坦率地说,似乎倾向于在代码级别显示工厂模式的机制,同时仅在叙述级别解释证明需要.希望工厂实际需求的代码级示例仍然很少。

谢谢。

【问题讨论】:

    标签: use-case factory-method


    【解决方案1】:

    在我看来,用例是维护和封装。 Factory 将返回的不是类本身,而是一个实现接口实现的对象。您可以根据需要切换类,用模拟或新接口实现替换它,而无需更改整个代码库(只要使用的类实现接口)。如果您使用新的接口实现,您只需更新一个文件。

    // Car.java
    public interface ICar {
        void drive();
    }
    
    // VWGolf.class
    public class VWGolf implements ICar {
        @Override
        public void drive() {
            System.out.println("VW Golf cruising around!");
        }
    }
    
    // VWPolo.class
    public class VWPolo implements ICar {
        @Override
        public void drive() {
            System.out.println("VW Polo cruising around!");
        }
    }
    
    // Mustang.java
    public class Mustang implements ICar {
        @Override
        public void drive() {
           System.out.println("Mustand driving around!");
        }
    }
    
    // CarFactory.java
    public class CarFactory {
        public ICar getVW(boolean isTestEnvironment){
            if (isTestEnvironment) {
                return new VWPolo();
            } else {
                return new VWGolf();
            }
        }
    
       public ICar getMustang(){
            return new Mustang();
        }
    }
    

    【讨论】:

    • 嗨,Ben,是否可以参考引用的代码来解释工厂返回的接口实现是什么意思?我对代码的阅读是工厂返回一个对象。如果认为对象是一个接口实现,那么我们回到问题——对象实例化不需要工厂。
    • 即使改变被实例化的子类,这只需要在实例化点进行编辑。许多工厂示例使用enum 枚举子类以赋予它们有意义的名称。然而,编辑枚举名称与在代码中编辑子类名称似乎没有什么不同。
    • 嗨@user2153235,我已经稍微更新了我的帖子以明确我的意思。关于你的第二个问题:仅仅因为你改变了子类,枚举或工厂方法不必改变。此外,最大的优势是您可以在运行时决定在一个位置使用哪个接口实现。在工厂方法中,您可以决定(例如,如果您在测试环境中)使用接口的另一个实现。
    • 我讨厌发表此评论,因为我看到您已经花了一些时间来组装代码级示例,但您的回答似乎就是我首先发布问题的原因。也就是说,我找到了工厂机制的代码级示例,以及解释正在解决的问题的高级叙述。是否有在线示例显示没有工厂的代码来说明问题所在?希望所有语言的推理都是相同的(C++,我的知识已经有将近 2 年的历史了,而 Java,我对它知之甚少)。
    • 我无法根据高水平的叙述来描绘它。使用工厂,您可以通过更改工厂方法的参数值来更改要实例化的子类。如果没有工厂,您将更改要实例化的子类的名称。在这两种情况下,所需的编辑量似乎相同。我敢肯定,需要工厂的实际情况并不像这样简单,这就是为什么这个问题是关于在没有工厂的情况下在代码级别识别问题的原因。
    【解决方案2】:

    我对此讨论有点晚了,但希望这对未来的读者有所帮助。

    下面是一个很好的链接,其中包含一个玩具制造商的简单示例用例。虽然示例代码是 php,但我认为设计模式很清晰,它从一个简单的设计模式开始,并讲述了为什么简单模式不再适用于玩具制造商的故事: https://www.binpress.com/factory-design-pattern/

    抽象工厂设计模式的描述对我来说仍然有点混乱,但是在阅读了下面的链接后,它有一个 C++ 代码示例,我明白了一点: https://iq.opengenus.org/abstract-factory-pattern-cpp/

    【讨论】:

      猜你喜欢
      • 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
      相关资源
      最近更新 更多