web-dev-qa-db-ja.com

エレベーター設計の課題

OOPスキルを強化する必要があるため、エレベーターシミュレーターを実装することを考えました。最初は、シンプルなデザインのように見えたものが完全に混乱し、OOPの知識について混乱しました。以下は実装クラスです。

/**
 * 1. User enter the elevator.
 * 2. Elevator checks the maximum capacity.
 * 3. User enters the floor number.
 * 4. Elevator registers the request.
 * 5. Elevator checks the next request and stops at that floor.
 * 6. When elevator is in the halt state the door opens.
 */

enum State {
  UP,
  DOWN,
  HALT
}

enum Command {
  ALARM,
  OPEN,
  CLOSE,
  GROUND,
  FIRST,
  SECOND
}

enum Floor {
  GROUND,
  FIRST,
  SECOND
}

interface Engine {
  public void moveTO(Floor floor);
}

interface Alarm {
  public void ring();
}

interface Sensor {
  public int getWeight();
  public int shouldCloseDoor();
}

final class Panel {
  private final Command[] commands;
  private final Elevator elevator;

  Panel(Command[] commands, Elevator elevator) {
    this.commands = commands;
    this.elevator = elevator;
  }

  public void onKeyPress(Command command) {
    if (command == Command.OPEN) {
      elevator.stop();
    } else if (command == Command.CLOSE) {
      elevator.move();
    } else if (command == Command.GROUND) {
      elevator.gotoFloor(Floor.GROUND);
    } else if (command == Command.FIRST) {
      elevator.gotoFloor(Floor.FIRST);
    } else if (command == Command.SECOND) {
      elevator.gotoFloor(Floor.SECOND);
    }
  }
}

final class Door {
  private boolean final open;

  Door() {
    open = false;
  }

  public void open() {
    if (open) return;
    try {
      Thread.sleep(1000); //1000 milliseconds is one second.
      open = true;
    } catch(InterruptedException ex) {
      Thread.currentThread().interrupt();
      close();
    }
  }

  public void close() {
    open = false;
  }
}

// Handle elevator logic. Here the assumption is that the elevator has to come
// back to ground floor if there are not any pending requests. There are two
// queues which handles the floor requests, the elevator keeps moving in the
// direction of the queue until that queue is not empty. If the elevator reaches 
// the top floor and there is no pending request then the elevator comes down to
// ground floor and comes to the halting state.
class Elevator {
  public static final int MAX_WEIGHT_ALLOWED = 1600;

  private final State state;
  private final Door door;
  private final Floor floor;
  private final Queue<Floor> queueUp;
  private final Queue<Floor> queueDOwn;
  private final Engine engine;
  private final Sensor sensor;
  private final Alaram alarm;

  Elevator(Door door, Engine engine, Sensor sensor, Alaram alarm) {
    this.door  = door;
    this.queueUp   = new Queue<Floor>();
    this.queueDown = new Queue<Floor>();
    this.state  = State.HALT
    this.floor  = Floor.ZERO;
    this.engine = engine;
    this.sensor = sensor;
    this.alarm  = alarm;
  }

  public void stop() {
    door.open();
    state = State.HALT;
    engine.stop();
    System.out.println("Elevator is in stopped state.");
  }

  private void moveUp() {
    while(!queueUp.isEmpty()) {
      floor = queueUp.dequeue();
      engine.moveTO(floor);
    }
    // All up requests are served.
    state = state.DOWN;
    gotoFloor(Floor.ZERO);
  }

  private void moveDown() {
    while(!queueDown.isEmpty()) {
      floor = queueUp.dequeue();
      engine.moveTO(floor);
    }
    // All down requests served.
    state = State.UP;
  }

  public void move() {
    if (sensor.getWeight() > Elevator.MAX_WEIGHT_ALLOWED) {
      alarm.ring();
      stop();
      return;
    }
    if (!sensor.shouldCloseDoor()) {
      alarm.ring();
      stop();
      return;
    }
    door.close();
    if (state == State.UP) {
      moveUp();
    } else if (state == State.DOWN) {
      moveDOwn();
    }
    // Both the queues are empty
    state = State.HALT;
    System.out.println("Elevator is moving to floor: " + );
  }

  public void gotoFloor(Floor nextFloor) {
    if (floor < nextFloor)
      queueDown.enqueue(floor);
    else
      queueUp.enqueue(floor);
    move();
  }
}


public class ElevatorSimulator {
  public static void main(String[] args) {
    Elevator elevator = new Elevator(
      new Door(), new Engine(), new Sensor(), new Alarm());
    Panel panel = new Panel(Command.values(), elevator);

    panel.onKeyPress(Command.OPEN);
    panel.onKeyPress(Command.CLOSE);
    panel.onKeyPress(Command.FIRST);
  }
}

要件を考えて書き留めることは大いに役立つと聞いて、私もそれを試しましたが、そのシナリオでも完全に失敗したと思います。

質問

  1. 一連の要件を決定するための優れた戦略。
  2. 気が散る詳細に切り替えるのではなく、認知的過負荷を避け、高レベルの設計に集中してください。
  3. 依存関係を一覧表示して管理します。
  4. 全体的に良いデザインにアプローチする方法:)
2
CodeYogi

レイヤードデザインを作成しようとしています。

最上層には、エレベータのライダーと対話する入力と出力があります。入力は、エレベータのボタンパネルと、エレベータの階数の表示、および上下のインジケータとボタンが押されたインジケータです。さらに、各フロアにアップ/ダウンコールボタンがあります(ディスプレイの複製)。この部分は非常に単純です。エレベータにボタンのパネルがあり、上下の呼び出しボタンの可変(フロアごと)セット、およびディスプレイ(複製されます)があります。 (もちろん、実験的または派手にならない限り、標準とは異なるボタンを使用してエレベーター機能を改善することができます...)

真ん中には、実装の詳細を隠す抽象化があります。つまり、公平性とフロアを選択し、フロアごとのリクエストと他のフロアごとのリクエストおよびエレベータ上のリクエストのバランスをとるアルゴリズムです。

最下層には、読み取るセンサーと制御するアクチュエーターがあります。ここで、より厳密さが必要だと思われます。デザイン要素は私には不均一に見えます。ドアはクラスで表され、エンジンはインターフェースで表されます。単一のセンサーインターフェイスがあります。特定のタイプの複数のセンサーが表示されることを期待しています。センサーインターフェースには、ドアを閉める必要のある方法があります。また、アクチュエータを明確に呼び出す必要があります。

この最下層を完全に理解するまで、アルゴリズムを設計したりクラスをコード化したりしないでください。これらの機能、およびそれらがどれほどインテリジェントであるかについて、真剣な考えや研究を行う必要があります。たとえば、ドアが開いているかどうかに関係なく、モーターによってエレベータを動かすことができますか?もしそうなら、あなたのエレベーターのアルゴリズムはドアが開いている間は動かないようにする必要があります。そうでない場合、エレベーターアルゴリズムは、インテリジェントおよび安全処理の一部を別のセミインテリジェントコントローラーと共有しています。つまり、エレベーターアルゴリズム内でこれらの機能を複製、複製、またはキャッシュする必要はありません。

エレベータの構成もあります。最大の項目は、実際のフロア数のカウントです。各フロアについては、フロア上に上下のリクエストボタン用のパネルが期待できます。 -エレベーターパネルのボタンは、フロア数を反映しています。

基本的に、あなたは自分のコードによって何をモデル化しているのか、そしてその理由を決定する必要があります。目的なしに何かをモデル化することはできないということわざがあります。モデルは、内部を見て賞賛するだけでなく、外部から非常に具体的なことを行うことです。 「なぜモデル化するのか」に対する答えは、入力に応答する動作を示す必要があるためです。具体的には、その動作は適切なアクチュエータの適切なタイミングでのトリガーに現れます。それ以外の場合は、不要なものをモデル化しないでください。すでに他の何かによってモデル化されているもののモデリングを複製しないでください。たとえば、ドアが開いているかどうかを認識している場合は、アルゴリズムでドアの開閉状態を複製するのではなく、そのインターフェイスを使用します。

したがって、最上位層から始めて、ボタンとディスプレイを提供するインターフェースを指定します。次に、センサーとそのインターフェース、および制御が必要なアクチュエーターとそのインターフェースを特定します。次に、インテリジェンスがシステムのどこにあるか(何が欠けているか、どこにある必要があるか)を把握します。これは、センサー/アクチュエーターデバイスのスマートさによって大きく異なります。次に、最上部(ユーザー)層と最下部(センサー/アクチュエーター)層の間に位置するスマートで安全なエレベータハンドラーを設計できます。

基本的に、外側から内側にデザインする必要があります(最初に上下、次に中央)。そうしないと、モデリングしているもの(中央)とその理由がわかりません。

3
Erik Eidt