OOP設計の問題。2種類の空のオプション


8

ホテルの部屋の予約を扱う非常にシンプルなアプリケーションを書いています。ある段階で問題が発生しました。

注文のキューを処理しています。注文ごとに、受付係の1人は、クライアントの戦略に従って部屋(1つまたはまったくなし)を選択する必要があります。それが私がJavaを使うことにした理由Optionalです。問題は、希望する日に空き部屋がない場合は注文をキャンセルする必要があることですが、利用可能な部屋があり、それらのどれもが受付の戦略に適合しない場合は、注文をキューに戻す必要があります。

部屋を選択することは間違いなく受付の義務である必要があります。その問題にクリーンな方法で対処するための最良の方法は何だと思いますか?Optional日付に部屋がない場合、空を返す代わりに例外をスローする必要がありますか?残念ながら、例外は通常、コードフローを制御するための適切なソリューションではありません。

コードフラグメント:

    Optional<Room> selectedRoom = receptionist.chooseRoom(rooms, 
                                                          order.getQuestionnaire());

    boolean decision = selectedRoom
            .map(room -> receptionist.askClient(order.getClient(), 
                                                room,
                                                order.getQuestionnaire()))
            .orElse(false);

    if (shouldProcessAgain(order, selectedRoom.isPresent(), decision)) {
        orders.add(order);
    }

1
注文をキューに戻すと、どのようなメリットがありますか?レセプションは何度も何度も失敗しませんか?
Winston Ewert 2016

@WinstonEwertいいえ。注文に対応する受付担当者はたくさんいて、選択戦略はさまざまです。
パヴェルKoniarski

@WinstonEwertホテルの状態が変わるまではそうだと思います。
candied_orange

@PawełKoniarskiは、この文脈で「戦略」を定義してください
candied_orange

1
うん、まさにそのようです。受付係はサイクルでループされ、次の注文はすべて他の受付係によって処理されます。
パヴェルKoniarski

回答:


1

2つの方法でモデル化できると思います。

オプション1:受付応答にラッパー+列挙型を使用する:

enum ReceptionistDecision {
    BOOK_ROOM,
    NO_ROOM,
    RETURN_TO_QUEUE,
}

class ReceptionistResponse {
    ReceptionistDecision Decision;
    Optional<Room> Room;

    ReceptionistResponse(Room room) {
        ...
    }

    ReceptionistResponse(ReceptionistDecision decision) {
        ...
    }
}

オプション2:または、インターフェースクラスを作成して、各レスポンスがそれから継承するようにすることもできます。何かのようなもの:

interface class ReceptionistResponse {

}

class ReturnToQueueReceptionistResponse implements ReceptionistResponse {

}

class NoRoomsBookedQueueReceptionistResponse implements ReceptionistResponse {

}

class RoomBookedReceptionistResponse implements ReceptionistResponse {
    Room BookedRoom;
}

chooseRoomこの方法は、次のようになります。

ReceptionistResponse chooseRoom(List<Rooms> allRooms, Questionnaire questionnaire) {
    if (/* all rooms are full */) {
        // Option 1
        return new ReceptionistResponse(ReceptionistDecision.RETURN_TO_QUEUE);

        // Option 2
        return new ReturnToQueueReceptionistResponse();
    }

    if (/* Choose no rooms */) {
        // Option 1
        return new ReceptionistResponse(ReceptionistDecision.NO_ROOM);

        // Option 2
        return new NoRoomsBookedQueueReceptionistResponse();
    }

    if (/* Choose some room */) {
        // Option 1
        return new ReceptionistResponse(choosenRoom);

        // Option 2
        return new RoomBookedReceptionistResponse(choosenRoom);
    }
}

オプション1のクライアントコード:

ReceptionistResponseレスポンス= ceptionist.chooseRoom(rooms、order.getQuestionnaire());

// options 1
if (response.Decision == ReceptionistDecision.RETURN_TO_QUEUE) {
// option 2
if (response instanceof(ReturnToQueueReceptionistResponse)) {

    orders.add(order);
}

私はあなたの最初の選択肢に近いものを使うことにしました。ご協力ありがとうございます。
パヴェルKoniarski

5

これをモデル化するために適用できるアプローチがいくつかあります。

まず、受動的な受付係がいるかもしれません。受身の受付係は何をすべきかを決定しますが、何もしません。代わりに、次のようなクラスがあります。

public class ReceptionistResponse {
    public static ReceptionistResponse bookRoom(Room room);
    public static ReceptionistResponse cancelOrder();
    public static ReceptionistResponse returnToQueue();
}

これがオプションと同じ基本的な考え方であることに気づいたかもしれませんが、1つではなく3つのオプションに拡張しました。各静的メソッドは、特定の応答を作成して返します。それからあなたの受付係は方法を持っています

ReceptionistReponse attemptBookOrder(Order order) {
    ...
    return ReceptionistResponse.bookRoom(room);
    ...
}

呼び出しコードはReceptionistResponseを受け取り、必要な応答を引き受けます。

または、アクティブな受付係がいるかもしれません。アクティブな受付係が実際にアクションを実行します。

void attemptBookOrder(Order order) {
    if (rooms.allRoomsAreFull()) {
       order.cancel();
    }
    if (...) {
       order.bookRoom(room);
    } else {
       orderQueue.put(order);
    }
}

3つの可能な応答を処理するためにReceptionistResponseをどのように構成しますか?列挙型とオプションの部屋フィールド?異なる応答のそれぞれに多数のプロパティ(たとえば、percentMatchedまたはroomsAvailable)があった場合はどうでしょうか?
AmadeusDrZaius

1
@AmadeusDrZaiusでは、オプションの列挙型または複数のサブクラスを使用できます。
Winston Ewert 2016

1

オプションを返すことは問題ないようですが、値がない場合、ロジックは続行されません。各ゲストには実際の部屋が割り当てられているか、ゲストではありません。したがって、受付係が空のオプションを返すことを決定すると、注文はキューに戻され、それ以上何も返されません。

最初にキューから注文を受け取ってから、receptionist.chooseRoomを実行し、それが空に戻った場合は、注文をキュー(の最後)に再度追加します。注文が失われないようにするために、これをtry-finallyに含めます。

部屋が選択された場合は、オプションではなく、部屋として処理する必要があります。Optionalは一時的な変数としてのみ使用する必要があります。その唯一の目的は、受付係が今のところ注文を処理しないことを決定したことを検出することです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.