当前位置: 首页 > 面试题库 >

在Java中实现工厂模式的最佳方法

从光启
2023-03-14
问题内容

我正在尝试编写工厂模式以在程序中创建MainMode或TestMode。我以前用来创建这些对象的代码是:

play = (isMode) ? new MainMode(numberRanges, numberOfGuesses) : 
                  new TestMode(numberRanges, numberOfGuesses, randNo());

我的游戏(游戏)将根据布尔值(isMode)创建MainMode对象或TestMode对象。如您所见,我正在向我的TestMode对象(randNo())添加一个额外的值。在TestMode中使用此值,以允许用户输入自己的“随机数”,而在MainMode构造函数中,则是随机生成的。在此程序中,MainMode和TestMode都是抽象类Game的子类。

现在,我想用工厂模式替换此行,尽管我不确定,因为我的TestMode构造函数需要一个额外的对象,而且我不确定需要在哪里传递此值。如果要创建Factory,则需要将其放在一个新类中,该类可能名为GameFactory或ModeFactory或类似的名称。

我将如何处理?

编辑:
这里的问题是上面的代码在我的GUI中,其中numberRanges,numberOfGuesses和randNo()方法的值是。我想创建一个Factory类,但是由于randNo()激活了自己,所以无法传递这些值。这是我的randNo()方法。

private int randNo() {
    boolean isValidNumber = true;
    int testRandomNum = 0;
    while(isValidNumber) {
        try {
            testRandomNum = Integer.parseInt(JOptionPane.showInputDialog("Enter Random Number"));
            isValidNumber = false;
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(null, "Sorry, but the number you entered was invalid");
        }
    }

    return testRandomNum;
}

问题是,每当我传递randNo()时,它就会显示JOptionPane。就像我已经说过的,GUI和逻辑是分开的。GUI位于GUI程序包中,而其余代码位于逻辑程序包中。


问题答案:

请注意,其他一些答案可能可以描述工厂,但不能描述 GOF Factory Pattern

现在,我想用工厂模式替换此行,尽管我不确定,因为我的TestMode构造函数需要一个额外的对象,而且我不确定需要在哪里传递此值。

好吧,您可以这样想:MainMode(而不是TestMode)是一种执行特殊操作的程序。它要做的特殊事情是 忽略
给定的数字,以确保它确实是随机的。通过这种思考方式,MainMode可以做更多的事情。

或者,如果除了随机性之外,MainMode和TestMode没有不同,那么您可能会认为可以将相似性分解为一个类,这是计算随机数的两种策略之一。一种策略实际上是随机的,而另一种则是错误的,其随机范围仅为1个值。

但让我们假设MainMode和TestMode之间还有其他区别-大概是TestMode将额外的调试输出到System.out或其他东西。

我们仍然可以从测试或玩游戏中排除“我们如何提供随机性”。这些都是 正交的 问题。

因此,现在我们知道,除了“模式”所做的一切之外,它还应该接受随机性策略。然后,例如,当您被告知标准平台随机性还不够真正随机时,您可以使用更好的随机性来代替它。

或者,您可以进行测试,其中将随机范围限制为仅两个选择,或者始终从一到零交替,或者在每次调用时返回某个Vecrtor或Iterator中的下一个值。

因此,我们使用GOF策略模式来构建随机性策略:

interface RandomStrategy { 
  public double random();
}

public class NotSoRandom implements RandomStrategy {
  private double r;
  public NotSoRandom( final double r ) { this.r = r; }
  public double random() { return r; }
}

public class PlatformRandom implements RandomStrategy {
  public double random() { return Math.random(); }
}

现在,如果您的整个应用仅创建了一个“模式”,则无需工厂。当您需要一遍又一遍地创建相同的类类型时,可以使用工厂;实际上,工厂只是用于创建正确种类的(子)类的策略。

在生产代码中,我曾使用过一些工厂,这些工厂中有一些通用类可以创建东西,并且我需要告诉如何创建正确的子类来创建。我经过一家工厂。

现在,我们为“模式”创建工厂模式;这将令人惊讶地类似于“策略”模式:

abstract class Mode() {
 private RandomStrategy r;
 public Mode( final RandomStrategy r ) { this.r = r; }
 // ... all the methods a Mode has
}

public class MainMode implements Mode {
  public MainMode( final RandomStrategy r ) { super(r); }
}

public class TestMode implements Mode {
  public TestMode( final RandomStrategy r ) { super(r); }
}

interface ModeFactory{ 
  public Mode createMode( final RandomStrategy r );
}

public class MainFactory() {
  public Mode createMode( final RandomStrategy r ) {
      return new MainMode(r);
  }
}

public class TestFactory() {
  public Mode createMode( final RandomStrategy r ) {
      return new TestMode(r);
  }
}

现在,您了解了工厂模式和策略模式,以及它们在“形状”方面的相似之处,但在用法上却有所不同:工厂模式是对象创建的,它返回要使用的对象;策略是对象行为的,通常会显式创建一个实例,并保留对该实例的引用以封装算法。但是就结构而言,它们非常相似。

编辑:OP在评论中询问“如何将其集成到我的GUI中?”

好吧,除了“模式”,所有这些都不属于程序的GUI。您将创建ConcreteStrategy,然后在某些设置例程中将其传递给首选的Factory,并可能根据命令行参数或配置文件确定要使用哪个。基本上,您会在选择原始帖子中的正确类别时非常选择正确的工厂。
再说一次,如果您只创建其中之一,则不需要Factory。 工厂用于批量生产(或创建相关具体类型的族,尽管这超出了此问题的范围)。

(假设我们有一个游戏,用户可以在命令行上选择是与机器人还是与龙搏斗;然后我们要实例化一个产生对手(接口)的OpponentFactory,并派生类RobotOpponent和DragonOpponent,并传递该工厂游戏中会生成NewOpponent()的部分。类似地,用户可能会选择勇敢或怯ward的对手(我们将其设置为策略)。我们不需要制作更多的策略实例,因为策略通常是幂等的(无状态和单例)。)

static int main( String[] args ) {
// setup game world

final RandomStrategy r = "random".equals(args[0]) 
  ? new PlatformRandom() : new  NotSoRandom( Integer.intValue(args[0]) ) ;
// notice the simlarity to the code you originally posted;
// we factored out how to achieve "randomness" as a Strategy.

// now we will use our Strategy to setup our Factory;

final ModeFactory f = "test".equals(args[1])
  ? new TestFactory(r) : new MainFactory(r);
// also similar to your code
// we've just added an extra level of indirection: 
// instead of creating a Mode, we've created an object that can create Modes
//  of the right derived type, on demand.

// call something that uses our factory
functionThatRunsameAndNeedstoProduceModesWhenevertNeedsTo( f );

}


 类似资料:
  • 我更喜欢第一种方式,因为我认为在构建器中重复它们是多余的。第一种方法是否存在一些缺点? 提前谢谢,抱歉我的英语不好。

  • 本文向大家介绍Java设计模式编程中的工厂方法模式和抽象工厂模式,包括了Java设计模式编程中的工厂方法模式和抽象工厂模式的使用技巧和注意事项,需要的朋友参考一下 工厂方法模式 动机 创建一个对象往往需要复杂的过程,所以不适合包含在一个复合工厂中,当有新的产品时,需要修改这个复合的工厂,不利于扩展。 而且,有些对象的创建可以需要用到复合工厂访问不到的信息,所以,定义一个工厂接口,通过实现这个接口来

  • 我有一个通用接口处理程序 我可以有n个这个接口的实现。假设我现在有以下两个实现。一个处理字符串对象,另一个处理日期 我想写一个工厂,它将根据类类型返回处理程序实例。比如: 我在这个工厂里遇到了以下错误: 类型不匹配:无法从转换为

  • 本文向大家介绍Java设计模式之工厂模式分析【简单工厂、工厂方法、抽象工厂】,包括了Java设计模式之工厂模式分析【简单工厂、工厂方法、抽象工厂】的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Java设计模式之工厂模式。分享给大家供大家参考,具体如下: 一、 简单工厂 先来思考一个问题。我们平时写程序时,会有这种情况,A对象里面需要调用B对象的方法,这时我们使用的一般是new关键字来创建

  • 本文向大家介绍工厂模式在JS中的实践,包括了工厂模式在JS中的实践的使用技巧和注意事项,需要的朋友参考一下 一.   写在前面  工厂模式和抽象工厂在后台代码中的使用,相信你一定非常熟悉,所以关于概念的东西也用不着我多说。你可以用其做为类与类之间,层与层之间的解耦。工厂模式没有什么难点,在JS中其实思想也是一样的,所以废话不多说,直接上实践的场景和代码。 二.  场景描述  1.最近的项目的登陆使

  • 亦称: 虚拟构造函数、Virtual Constructor、Factory Method 意图 工厂方法模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。 问题 假设你正在开发一款物流管理应用。 最初版本只能处理卡车运输, 因此大部分代码都在位于名为 卡车的类中。 一段时间后, 这款应用变得极受欢迎。 你每天都能收到十几次来自海运公司的请求, 希望应用