Vấn đề thiết kế OOP. Hai loại trống Tùy chọn


8

Tôi đang viết một ứng dụng khá đơn giản liên quan đến đặt phòng khách sạn. Tôi đã có một vấn đề ở một giai đoạn.

Tôi đang xử lý một hàng các đơn đặt hàng. Đối với mỗi đơn hàng, một trong những nhân viên tiếp tân nên chọn một phòng (một hoặc không có gì) cho khách hàng theo chiến lược của mình. Đó là lý do tại sao tôi quyết định đi với Java Optional. Vấn đề là nếu đơn giản là không có phòng miễn phí vào ngày mong muốn thì đơn hàng sẽ bị hủy, nhưng nếu có một số phòng có sẵn và không có phòng nào phù hợp với chiến lược của nhân viên tiếp tân thì nên đặt hàng trở lại hàng đợi.

Chọn phòng chắc chắn phải là nhiệm vụ của lễ tân. Bạn nghĩ gì là cách tốt nhất để giải quyết vấn đề đó một cách sạch sẽ? Tôi có nên ném một ngoại lệ thay vì trở về trống Optionalkhi không có phòng vào ngày? Thật không may, các trường hợp ngoại lệ thường không phải là một giải pháp tốt để kiểm soát dòng mã.

Đoạn mã:

    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
Những gì tốt để đặt trở lại trong hàng đợi làm gì? Không phải sự tiếp nhận chỉ thất bại nhiều lần?
Winston Ewert

@WinstonEwert Không. Có nhiều nhân viên tiếp tân giải quyết các đơn đặt hàng và họ có các chiến lược lựa chọn khác nhau.
Paweł Koniarski

@WinstonEwert Tôi sẽ giả sử như vậy cho đến khi tình trạng của khách sạn thay đổi.
candied_orange

@ PawełKoniarski vui lòng xác định 'chiến lược' trong bối cảnh này
candied_orange

1
Đúng, chính xác như thế. Nhân viên tiếp tân được lặp trong một chu kỳ và mỗi đơn hàng tiếp theo được phục vụ bởi nhân viên tiếp tân khác.
Paweł Koniarski

Câu trả lời:


1

Tôi nghĩ bạn có thể mô hình hóa nó theo hai cách:

Tùy chọn 1: Sử dụng trình bao bọc + enum cho phản hồi của nhân viên tiếp tân:

enum ReceptionistDecision {
    BOOK_ROOM,
    NO_ROOM,
    RETURN_TO_QUEUE,
}

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

    ReceptionistResponse(Room room) {
        ...
    }

    ReceptionistResponse(ReceptionistDecision decision) {
        ...
    }
}

Tùy chọn 2: Hoặc bạn có thể một lớp giao diện và làm cho mỗi câu trả lời được kế thừa từ nó. Cái gì đó như:

interface class ReceptionistResponse {

}

class ReturnToQueueReceptionistResponse implements ReceptionistResponse {

}

class NoRoomsBookedQueueReceptionistResponse implements ReceptionistResponse {

}

class RoomBookedReceptionistResponse implements ReceptionistResponse {
    Room BookedRoom;
}

Các chooseRoomphương pháp sẽ là:

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);
    }
}

Và mã máy khách cho tùy chọn 1:

Lễ tân phản hồi Phản hồi = tiếp tân.chooseRoom (phòng, order.getQuestionnaire ());

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

    orders.add(order);
}

Tôi đã quyết định đi với một cái gì đó gần với lựa chọn đầu tiên của bạn. Cảm ơn sự giúp đỡ của bạn.
Paweł Koniarski

5

Có một vài cách tiếp cận người ta có thể áp dụng để mô hình hóa điều này.

Đầu tiên, chúng ta có thể có nhân viên tiếp tân thụ động. Nhân viên tiếp tân thụ động quyết định phải làm gì, nhưng không làm gì cả. Thay vào đó, chúng tôi có lớp giống như

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

Bây giờ, bạn có thể nhận thấy rằng đây là ý tưởng cơ bản giống như tùy chọn, nhưng chúng tôi đã mở rộng nó thành ba tùy chọn thay vì chỉ một. Mỗi phương thức tĩnh tạo và trả về một phản hồi cụ thể. Sau đó nhân viên tiếp tân của bạn có một phương pháp

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

Mã cuộc gọi sẽ nhận được Lễ tân và phản hồi cần thiết.

Ngoài ra, bạn có thể có một nhân viên tiếp tân tích cực. Nhân viên tiếp tân tích cực thực sự làm các hành động:

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

Làm thế nào bạn sẽ cấu trúc Lễ tân phản hồi để xử lý ba phản hồi có thể? Một enum cộng với một lĩnh vực phòng tùy chọn? Thế còn một trường hợp trong đó các câu trả lời khác nhau có nhiều thuộc tính (ví dụ: phần trămMatched hoặc roomAv Available) thì sao?
AmadeusDrZaius

1
@AADEusDrZaius, bạn có thể sử dụng enum với tùy chọn hoặc nhiều lớp con.
Winston Ewert

1

Trả lại Tùy chọn có vẻ ổn nhưng nếu không có giá trị thì logic không nên tiếp tục. Mỗi khách có một phòng thực sự được chỉ định cho nó hoặc nó không phải là khách. Vì vậy, một khi nhân viên tiếp tân quyết định trả lại một Tùy chọn trống, đơn hàng sẽ được đưa trở lại vào hàng đợi và không có gì nữa.

Trước tiên, bạn có thể nhận đơn đặt hàng từ hàng đợi, sau đó thực hiện lễ tân.chooseRoom và nếu nó trở lại trống, hãy thêm lại thứ tự vào (cuối của) hàng đợi. Tôi sẽ gói nó trong một lần thử - cuối cùng để đảm bảo không có đơn hàng nào bị mất.

Nếu một phòng được chọn, nó sẽ tiến hành như một phòng, không phải là Tùy chọn. Tùy chọn chỉ nên được sử dụng như một biến tạm thời vì mục đích duy nhất của nó là phát hiện ra rằng nhân viên tiếp tân quyết định không xử lý đơn hàng trong thời điểm này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.