5

空港着陸システムをモデル化するプロジェクトを作成しています。私は、データベースに並べ替えて保存するために必要なすべての情報を保存するオブジェクトを持っていplaneます。すべての重要な情報がオブジェクトに含まれていますが、各平面の座標も含まれています。私の問題は、それぞれが多くの異なることを行うため、まとまりがあるとは見なされない可能性があることです.planequeueplane

これが悪い設計と見なされるかどうか、またはこれを行うためのより良い方法があるかどうかを知りたいだけですか?

また、オブジェクト内の結合の「ルール」とは何ですか? おそらくこれに対処できる特定の設計パターンはありますか?

public class Plane extends Aircraft {
/*
 * Flight status should only take one of these enum values
 */
private static enum Status {
    REGISTERED, IN_QUEUE, LANDING, LANDED
};

// Set aircraft status to REGISTERED when created
private Status status = Status.REGISTERED;

private double fuelLevelPercentage;
private int passengerCount;
private int aircraftNumber;
private String airlineCompany;
private String departureAirport;

// This is used by the constructor to assign a random city to each new Aircraft
private final String[] cities = { "Rome", "Berlin", "Heathrow",
        "Edinburgh", "Cardiff", "Dublin", "Stansted" };
// Used to set airline companies
private final String[] airLineCompanies =  { "Easyjet", "Ryanair", 
        "British Airways","Flybe","Air Lingus", "Virgin" }; 


// Random number generator used by the constructor
private Random rand;

// Thread for this instance of Aircraft
private Thread aircraftThread;

// Radius of path when flying in circle (km?)
private final double FLIGHT_RADIUS = 10;
// Time taken to complete one complete loop (ms)
private final double FLIGHT_PERIOD = 120000;
// Angular frequency omega (rad/s)
private double OMEGA = 2 * Math.PI / FLIGHT_PERIOD;
// Time taken between being directed to land, and landing (ms)
private int TIME_TAKEN_TO_LAND = 30000;

// Time take to use one percent of fuel (ms)
private double time_taken_to_use_one_percent_of_fuel = 30000;

// variable to keep track of time since instantiated (ms)
private int time = 0;
// The aircraft Thread sleeps for TIME_STEP between updating
private final int TIME_STEP = 20;

private int time_when_called_to_land;

private int hour_of_arrival;
private int minute_of_arrival;

/*
 *  Set coordinates at time zero
 */
private double x_coord = 0;
private double y_coord = FLIGHT_RADIUS;
private double altitude = 1000;

/*
 *  Used to calculate path to airport
 */
private double x_coord_when_called;
private double y_coord_when_called;
private double altitude_when_called;

Calendar calendar = Calendar.getInstance();

/**
 * This constructor sets the following fields to random values Dummy Data -
 * should have a better way to do this
 */
public Plane() {
    rand = new Random();

    this.fuelLevelPercentage = rand.nextInt(100);
    this.departureAirport = cities[rand.nextInt(cities.length)];
    this.passengerCount = rand.nextInt(500);
    this.aircraftNumber = rand.nextInt(50000000);
    this.airlineCompany = airLineCompanies[rand.nextInt(airLineCompanies.length)];
}

/**
 * this fly method will call on a different method depending on the status
 * of the Aircraft
 */
public void fly() {
    if (status == Status.REGISTERED) {
        useFuel();
    } else if (status == Status.IN_QUEUE) {
        flyInCircle();
        useFuel();
    } else if (status == Status.LANDING) {
        flyToAirport();
        useFuel();
    } else if (status == Status.LANDED) {

    }
}

public void flyInCircle() {
    x_coord = FLIGHT_RADIUS * (Math.cos(OMEGA * (time)));
    y_coord = FLIGHT_RADIUS * (Math.sin(OMEGA * (time)));
}

public void flyToAirport() {
    if (!(x_coord < 1 && x_coord > -1 && y_coord < 1 && y_coord > -1
            && altitude < 1 && altitude > -1)) {
        x_coord -= x_coord_when_called * TIME_STEP / TIME_TAKEN_TO_LAND;
        y_coord -= y_coord_when_called * TIME_STEP / TIME_TAKEN_TO_LAND;
        altitude -= altitude_when_called * TIME_STEP / TIME_TAKEN_TO_LAND;
    } else {
        System.out.println("Aircraft landed");
        status = Status.LANDED;
        hour_of_arrival = calendar.get(Calendar.HOUR_OF_DAY);
        minute_of_arrival = calendar.get(Calendar.MINUTE);
    }

}

/**
 * This method changes the flight status to IN_QUEUE - simulates telling the
 * plane to join queue
 */
public void directToJoinQueue() {
    setFlightStatus(Status.IN_QUEUE);
}

/**
 * This method changes the flight status to LANDING - simulates telling the
 * plane to land
 */
public void directToflyToAirport() {
    setFlightStatus(Status.LANDING);
    time_when_called_to_land = time;
    x_coord_when_called = x_coord;
    y_coord_when_called = y_coord;
    altitude_when_called = altitude;
}

/**
 * This method reduces fuel level according to fuel usage
 */
private void useFuel() {
    if (this.fuelLevelPercentage - TIME_STEP
            / time_taken_to_use_one_percent_of_fuel > 0) {
        this.fuelLevelPercentage -= TIME_STEP
                / time_taken_to_use_one_percent_of_fuel;
    } else {
        this.fuelLevelPercentage = 0;
    }
}

/**
 * this method sets the flight status
 */
private void setFlightStatus(Status status) {
    this.status = status;
}

public double getfuelLevelPercentage() {
    return fuelLevelPercentage;
}

public int getPassengerCount() {
    return passengerCount;
}

public void setPassengerCount(int passengerCount) {
    this.passengerCount = passengerCount;
}

public int getAircraftNumber() {
    return aircraftNumber;
}

public String getDepartureAirport() {
    return departureAirport;
}

public void stop() {
    ;
}

public String getAirlineCompany() {
    return airlineCompany;
}

public void setAirlineCompany(String airlineCompany) {
    this.airlineCompany = airlineCompany;
}

@Override
public String toString() {
    if (status == Status.LANDED) {
        return String
                .format("Flight %-8d | Fuel %-4.1f | Passengers %-3d | From %-10s | %-8s at %d:%d ",
                        aircraftNumber, fuelLevelPercentage,
                        passengerCount, departureAirport, status,
                        hour_of_arrival, minute_of_arrival);
    } else {
        return String
                .format("Flight %-8d | Fuel %-4.1f | Passengers %-3d | From %-10s | %-8s | Coords (%-3.2f,%-3.2f) | Altitude %-4.2f",
                        aircraftNumber, fuelLevelPercentage,
                        passengerCount, departureAirport, status, x_coord,
                        y_coord, altitude);
    }

}

public void start() {
    aircraftThread = new Thread(this, this.getClass().getName());
    aircraftThread.start();
}

@Override
public void run() {

    try {

        while (true) {
            calendar = Calendar.getInstance();
            fly();
            Thread.sleep(TIME_STEP);
            time += TIME_STEP;

        }

        // System.out.println("aircraft number "+aircraftNumber+" safely landed");

    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}
}
4

4 に答える 4

5

結束は難しい概念です。他の回答の軽薄な回答にもかかわらず、本当の答えは、システムが何を行い、どのように機能するかに大きく依存します。たとえば、キュ​​ーのメカニズムを調べてみましょう。あなたのシステムでは、キューに入っているときの飛行機のコマンドへの反応は異なりますか? もしそうなら、それがキューに入っているという事実は飛行機に不可欠なはずです. キューが異なれば、応答も異なりますか? もしそうなら、キュー自体はプレーンに統合されるべきです。ただし、飛行機がキューに入っているために空港が異なる応答をする場合は、空港がキューを制御する必要があり、飛行機はそれについて何も知らない必要があります.モデルの解像度によって異なります)。

ここでの問題は結束だけではありません。カプセル化も大きな問題です。他のオブジェクトが内部状態にアクセスできるようにしています。これを完全なオブジェクト指向の方法でモデル化するには、CQRS パターンの使用を検討する必要があります。DDD (ドメイン駆動設計) 手法も考慮し、境界付けられたコンテキストと集約ルートを特定することから始めると、正しい設計を導き出す可能性が高くなります。

于 2014-04-30T14:10:22.063 に答える
4

Java やその他の言語には「標準」はありません。

飛行機をキューに並べ替えてデータベースに渡すために必要なすべての情報を格納する「飛行機」オブジェクトがあります。すべての重要な情報がオブジェクトに含まれていますが、各平面の座標も含まれています。

Plane モデル オブジェクトが多すぎると思います。

キューに入っているかどうかを知る必要がある理由がわかりません。キューを所有する別のオブジェクトにルールを知ってもらいます。

キューはメモリ内コレクションですか、それともメッセージ キューですか? それはあなたにとって重要ですか?

自分自身を永続化するモデル オブジェクトは、議論のポイントです。永続性を別のデータ アクセス オブジェクトに分離する方が簡単で、テストしやすいと思います。

モデルは次のようになります。

package model;

public class Plane {

   private int id;
   public void save() { 
      // persist the state of this
      // INSERT INTO PLANE(id) VALUES(?)
   }
}

別のパッケージにDAOインターフェイスがあります:

package persistence;

public interface PlaneDAO {
    void save(Plane p);
}
于 2014-04-30T14:02:02.363 に答える
1

オブジェクトの結合に関する Java 標準はありません。(私はダッフィーモのアドバイスを繰り返さない、私はそれらすべてに同意する).

現実世界をマッピングするオブジェクト モデルを作成する際に心に留めておくべきことの 1 つは、現実世界の 1 つの概念をマッピングする1つのクラスを持つようにすることです。

例として、サンプル コードには少なくとも 2 つの異なる概念がPlaneありFlightます。したがって、それらを 1 対多の関係を持つ 2 つの別個のクラスに分割できます。

于 2014-04-30T14:17:39.113 に答える