1

好的,所以我有一个很大的类结构,看起来像这样

它是为学校准备的,我的教练喜欢星际争霸,所以就随它去吧。

无论如何,我在GeneratorBuilding类中有一个方法,它应该能够实例化一个新的海洋对象。但是我需要知道一个Marine对象需要多少资源。

我在名为 unitCost()的抽象Unit类中有一个抽象 int 方法。然后Marine类覆盖这个方法并返回一个类似 50 的值。

我正在寻找一种方法让我的GeneratorBuilding类获取Marine类中 unitCost() 方法的返回值,而无需调用任何特定的 Marine 对象。

我知道我可能会创建一个海洋对象,然后询问它的成本是多少,然后如果我没有资源,我会删除该对象而不是将其推入 ArrayList。但这似乎几乎是一种解决方法。

编辑:重点是能够让我所有的具体类继承和覆盖 UnitCost() 方法。所以我可以让它成为静态的,但这会破坏继承结构的全部意义......

EDIT2:由于有示例代码的请求(不完全难以想象)

public void makeMarine(){

    //uses resources and throws exception etc if there are not enough resources
    Game.useResources(Marine.unitCost());

    //creates a marine
    Game.addMarine();
}
4

3 回答 3

2

如果你真的想要一个好的、抽象的 OO 解决方案来解决这个问题,你应该使用抽象工厂模式

基本上,这意味着您创建一个“工厂”类,其唯一工作是创建特定类型的单元。工厂类的好处是您可以创建一个接口来表示您的整个工厂集,然后传递工厂的实例——这对于普通的类构造函数来说实际上是无法做到的。

一种常见的模式(我在这里推荐)是使用匿名内部类和抽象工厂类或接口来为每个单元类型创建“工厂”的单个实例。

这里有一些示例代码可以帮助您入门:

/**
 * Abstract class for Starcraft units
 */
public abstract class AUnit {
  // . . .
}

/**
 * Abstract factory for creating Starcraft units
 */
public abstract class AUnitFactory {
  public abstract int unitCost();
  public abstract AUnit createUnit();
}

public class Marine extends AUnit {

  public static final int COST = 50;

  /**
   * Using an anonymous inner class to create an
   * AUnitFactory instance for Marines
   */
  public static final FACTORY = new AUnitFactory() {
    public int unitCost() { return COST; }
    public AUnit createUnit() { return new Marine(); }
  }

  // . . .

}

public class Zergling extends AUnit {

  public static final int COST = 25;

  /**
   * Using an anonymous inner class to create an
   * AUnitFactory instance for Zerglings
   */
  public static final FACTORY = new AUnitFactory() {
    public int unitCost() { return COST; }
    public AUnit createUnit() { return new Zergling(); }
  }

  // . . .

}

/**
 * Starcraft game!
 */
public class Game {

  public addUnit(Player player, AUnitFactory unitFactory) {
    // Get unit's cost
    int cost = unitFactory.unitCost();
    // Now deduct it from the player's resources
    // . . .
    // Create the unit
    AUnit unit = unitFactory.createUnit();
    // Now add the unit to the game for the given player
    // . . .
  }

  // . . .

}

现在你可以做类似的事情Game.addUnit(player1, Zergling.FACTORY)or Game.addUnit(player2, Marine.FACTORY)

好处是您可以传递FACTORY实例,因为它们只是 type 的对象AUnitFactory。这意味着您可以执行一些操作,例如使用组合框来选择单位类型,然后在单击时创建一个按钮,该按钮会创建当前在组合框中选择的任何单位类型。

于 2013-04-19T05:03:55.443 回答
2

您可以通过在每个类中声明一个专门命名的静态字段并通过反射获取它来做到这一点}。

假设您的课程如下所示:

class ClassNumber1 {
    public static final int cost = 123;
}
class ClassNumber2 {
    public static final int cost = 321;
}

然后你可以cost像这样获取他们的字段:

public static <T> int getCost(Class<T> cl) throws Exception {
    // This is oversimplified: you need to check that the class
    // indeed has a field called "cost" by null-checking the return value
    // of getField(), verifying your cast, catching exceptions, and so on.
    // But this will work in a "closed" system, when you know for sure
    // that an int constant field does exist:
    return (int)cl.getField("cost").get(null);
}

您按如下方式调用该方法:

System.out.println(getCost(ClassNumber1.class));
System.out.println(getCost(ClassNumber2.class));

这是关于 ideone 的演示

于 2013-04-19T01:45:43.133 回答
0

这正是类方法的用途。在类方法中,unitCost()是Marine类本身的方法(即static public int UnitCost()),所以可以调用Marine.unitCost(),而不是m =new Marine()再调用m.UnitCost( )。

很酷的导师。希望我在服用 OO 时有一个。

于 2013-04-19T01:36:04.820 回答