私はRTSゲームを作成していますが、その機能の1つは、さまざまな種類の建物を構築することです。多くの繰り返しを見つけて、ヘルパーメソッドでそれを抽出することを考えていましたが、問題は、すべての建物が異なるオブジェクトであり、メインの建物クラスの一部のプロパティを継承していることです。
構築方法は次のようになります。
public static void buildDockyard(Base base) {
if (Validator.checkForBuilding(base, "Dockyard")) {
throw new IllegalStateException("Dockyard is already build");
}
Dockyard dockyard = new Dockyard("Dockyard");
int requiredPower = dockyard.requiredResource("power");
int requiredStardust = dockyard.requiredResource("stardust");
int requiredPopulation = dockyard.requiredResource("population");
Validator.checkResource(base, requiredPower, requiredStardust, requiredPopulation);
updateResourceAfterBuild(base, requiredPower, requiredStardust, requiredPopulation);
dockyard.setCompleteTime(dockyard.requiredResource("time"));
base.getBuildings().add(dockyard);
}
public static void buildHotel(Base base) {
if (Validator.checkForBuilding(base, "Space Hotel")) {
throw new IllegalStateException("Space Hotel is already build");
}
SpaceHotel spaceHotel = new SpaceHotel("Space Hotel");
int requiredPower = spaceHotel.requiredResource("power");
int requiredStardust = spaceHotel.requiredResource("stardust");
int requiredPopulation = spaceHotel.requiredResource("population");
Validator.checkResource(base, requiredPower, requiredStardust, requiredPopulation);
updateResourceAfterBuild(base, requiredPower, requiredStardust, requiredPopulation);
spaceHotel.setCompleteTime(spaceHotel.requiredResource("time"));
base.getBuildings().add(spaceHotel);
base.setCapacity(base.getCapacity() + spaceHotel.getCapacity());
}
私はこのようにリファクタリングすることを考えていました:ヘルパーメソッド
private static void construct(Building building, Base base) {
int requiredPower = building.requiredResource("power");
int requiredStardust = building.requiredResource("stardust");
int requiredPopulation = building.requiredResource("population");
Validator.checkResource(base, requiredPower, requiredStardust, requiredPopulation);
updateResourceAfterBuild(base, requiredPower, requiredStardust, requiredPopulation);
building.setCompleteTime(building.requiredResource("time"));
}
狙った結果
public static void buildDockyard(Base base) {
if (Validator.checkForBuilding(base, "Dockyard")) {
throw new IllegalStateException("Dockyard is already build");
}
Dockyard dockyard = new Dockyard("Dockyard");
construct(dockyar, base);
base.getBuildings().add(dockyard);
}
問題は、各建物に固有のプロパティとリソース要件があり、メインのBuildingクラスがそれらを認識していないため、ヘルパーメソッドのパラメーターとして使用できないことです。
これはすべて、Baseクラスの静的ヘルパークラスで発生しています。
このコードをどのようにリファクタリングしますか?前もって感謝します !
ゲームを作成するときにJavaでDRYを実行する最良の方法は、ゲームを明確に理解し、用語を理解することです。あなたはどの読めば現代のマニュアルボードゲームを、あなたはすぐに彼らは次のように、1つの概念のために正確に一つの単語を使用することがわかりますTurn
、Round
、Building
、Player
、Resource
。これにより、大まかな構造を形成できます。AにBuilding
は一定のコストがかかりますResource
。プレーヤーが十分でない場合は、Resource
「ベスパインガスがもっと必要です」などと伝えます。画像が鮮明であるほど、Javaが乾燥し、コードに必要なクラスを簡単に作成できます。
パラメーター
あなたがこのようなものになってしまう場合:
public static void someFunction(Base base, Object param1, Object param2)
public static void someOtherFunc(Base base, Object paramA, Object paramB)
...
次に、これは、おそらく両方の関数がBase
クラスの一部である必要があるという強力なヒントです。
列挙型
値のセットが限られている場合、Java列挙型はそれらを表すのに最適です。たとえば、リソースシステム:
public enum Resource {
POWER, STARDUST, POPULATION
}
これで、「スターダスト」、「スターダスト」と呼んだのか、「スターダスト」のようなリソースがまだあるのかを覚えておく必要はありません。代わりに使用できますint requiredPower = building.requiredResource(Resource.POWER);
ポリモーフィズム
我々は2つのクラスを持っている、としましょうBuilding
とStarHotel
で、StarHotel
特定の種類であることBuilding
。抽象クラスを持つBuilding
ことで、次のような特定の方法でいくつかの一般的なメカニズムを処理できます。
public abstract class Building {
private ... cost;
private ... requirements;
private ...
// Std-Getter and Setter methods
public ... getCost() { return this.cost; }
}
すべての建物には、コスト、要件、その他の重要な変数があります。しかし、これらの汎用変数を取得して基本クラスに設定するという標準的な作業はすべて処理しました。基本クラスから、他のより具体的な建物を拡張できます。extends
キーワードのおかげで、繰り返しのゲッターとセッターでクラスをStarHotel
埋めることなく、オブジェクトのコストを取得できますStarHotel
。
public class StarHotel extends Building {
// Getter, Setter inherited from Building class
}
インターフェイス
Javaインターフェースを使用すると、メソッドを定義するインターフェースを定義できます。素人の言葉で言えば:インターフェースが実装を提供しない限り、インターフェースを実装するすべてのクラスがメソッドを実装する必要があるため、これは便利ですdefault
。
public interface ResourceProvider {
void provideResourceFor(Base base); // A Resource Provider provides Resource for a base.
}
このインターフェースを使用して、一部のクラスが実装ResourceProvider
する場合、一部のBase
オブジェクトに提供するリソースの方法と内容を指定する必要があることを定義しました。私たちのインターフェースは、どのリソース、どのベース、そして何provideResourceFor
を意味するかさえ気にしませんが、何かが実装されResourceProvider
ている限り、それは機能を提供しなければなりません。
すべてをまとめる
列挙型、インターフェイス、およびポリモーフィズムを組み合わせて、StarHotel
拡張Building
および実装するクラスを作成し、ResourceProvider
8つのFoodユニットと2つのHappinessユニットをBaseに提供できるようになりました。
public class StarHotel extends Building implements ResourceProvider
public void provideResourceFor(Base base) {
base.addResource(Resource.FOOD, 8);
base.addResource(Resource.HAPPINESS, 2);
}
}
それは理解するのに大変かもしれませんが、うまくいけば、それはあなたにさらに見るべき良い方向性を与えるでしょう。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加