You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Java OOP概念建模按夜计费房产租赁系统的关联关系

核心问题解答

1. 必须单独定义业主类,原Property中的ownerName属性建议移除

遵循单一职责原则,业主是独立的业务实体,除姓名外还会有ID、联系方式、结算账户等专属属性,不适合耦合在房产类中。且业主和房产是典型的一对多关联关系,由业主类持有房产集合的设计扩展性更好,后续新增业主相关的业务逻辑(比如佣金结算、房源上下架管理)也更方便。

2. 业主与房产的关联实现方案

  • 首先优化Property基类:移除ownerName,新增ownerId字段做反向关联(方便快速查询房产所属业主),同时补充日期维度的占用状态存储(满足按日期预订的需求),补全占用状态相关的get/set方法。
  • 定义Owner业主类:核心包含业主基础属性 + 名下房产集合,提供房源的新增/移除/可用查询方法。

代码示例如下:

// 优化后的Property基类
public class Property {
    private String description;
    private int propertyPrice;
    private Long ownerId; // 关联业主ID,用于反向查询
    // 替换原isOccupied,存储不同日期的占用状态,key为预订日期,value为是否已被占用
    private Map<LocalDate, Boolean> occupancyMap = new HashMap<>();

    // 原有get/set保留,新增占用状态校验方法
    public boolean isAvailable(LocalDate date) {
        return !occupancyMap.getOrDefault(date, false);
    }

    public void setOccupied(LocalDate date, boolean isOccupied) {
        occupancyMap.put(date, isOccupied);
    }

    public Long getOwnerId() {
        return ownerId;
    }

    public void setOwnerId(Long ownerId) {
        this.ownerId = ownerId;
    }
}

// 业主类定义
public class Owner {
    private Long ownerId;
    private String name;
    private String contactInfo;
    // 持有名下所有房产的集合
    private List<Property> properties = new ArrayList<>();

    // 新增房产到业主名下
    public void addProperty(Property property) {
        property.setOwnerId(this.ownerId);
        properties.add(property);
    }

    // 查询业主名下指定日期可用的房产
    public List<Property> getAvailableProperties(LocalDate date) {
        return properties.stream()
                .filter(p -> p.isAvailable(date))
                .collect(Collectors.toList());
    }

    // 其他get/set方法省略
}

// 客户类定义(预订主体必须单独建模)
public class Customer {
    private Long customerId;
    private String name;
    private String contactInfo;
    // 可加预订记录集合,存储客户的历史预订信息
    private List<BookingRecord> bookingRecords = new ArrayList<>();
    // 其他get/set方法省略
}

3. registry函数预置条件实现逻辑

首先需要一个全局的系统上下文类,存储系统预置的业主、客户、所有房产的索引数据,初始化阶段就把预置数据加载完成:

// 系统上下文类,存储全局数据
public class RentalSystemContext {
    public static Map<Long, Owner> ownerMap = new HashMap<>();
    public static Map<Long, Customer> customerMap = new HashMap<>();
    public static Map<Long, Property> allPropertyMap = new HashMap<>();
    private static Long propertyIdGenerator = 1L;

    // 系统初始化方法,实现预置条件
    public static void init() {
        // 1. 初始化2个业主
        Owner owner1 = new Owner(1L, "业主1", "联系电话1");
        Owner owner2 = new Owner(2L, "业主2", "联系电话2");
        ownerMap.put(owner1.getOwnerId(), owner1);
        ownerMap.put(owner2.getOwnerId(), owner2);

        // 2. 初始化1号业主的房产:10间30美元标准酒店房,3间60美元套房
        for (int i = 0; i < 10; i++) {
            Hotel standardRoom = new Hotel();
            standardRoom.setDescription("标准酒店客房-" + i);
            standardRoom.setPropertyPrice(30);
            standardRoom.setRoomType("Standard"); // 优化原Hotel类,单个实例存对应房型即可
            owner1.addProperty(standardRoom);
            allPropertyMap.put(generatePropertyId(), standardRoom);
        }
        for (int i = 0; i < 3; i++) {
            Hotel suiteRoom = new Hotel();
            suiteRoom.setDescription("套房酒店客房-" + i);
            suiteRoom.setPropertyPrice(60);
            suiteRoom.setRoomType("Suite");
            owner1.addProperty(suiteRoom);
            allPropertyMap.put(generatePropertyId(), suiteRoom);
        }

        // 3. 初始化2号业主的房产:3套70美元公寓,5套20美元民宿
        for (int i = 0; i < 3; i++) {
            Apartment apartment = new Apartment();
            apartment.setDescription("公寓-" + i);
            apartment.setPropertyPrice(70);
            owner2.addProperty(apartment);
            allPropertyMap.put(generatePropertyId(), apartment);
        }
        for (int i = 0; i < 5; i++) {
            HomestayRoom homestay = new HomestayRoom();
            homestay.setDescription("民宿-" + i);
            homestay.setPropertyPrice(20);
            owner2.addProperty(homestay);
            allPropertyMap.put(generatePropertyId(), homestay);
        }

        // 4. 初始化2个客户
        Customer customer1 = new Customer(1L, "客户1", "联系电话A");
        Customer customer2 = new Customer(2L, "客户2", "联系电话B");
        customerMap.put(customer1.getCustomerId(), customer1);
        customerMap.put(customer2.getCustomerId(), customer2);
    }

    private static Long generatePropertyId() {
        return propertyIdGenerator++;
    }
}

registry函数实现,先校验所有预置条件再执行预订:

/**
 * 预订函数
 * @param customerId 客户ID
 * @param bookDate 预订日期
 * @param propertyIds 要预订的房产ID列表
 * @return 预订是否成功
 */
public boolean registry(Long customerId, LocalDate bookDate, List<Long> propertyIds) {
    // 预置条件校验1:客户是否已注册
    if (!RentalSystemContext.customerMap.containsKey(customerId)) {
        throw new IllegalArgumentException("客户未注册");
    }
    // 预置条件校验2:所有预订房产在指定日期是否可用
    for (Long propertyId : propertyIds) {
        Property property = RentalSystemContext.allPropertyMap.get(propertyId);
        if (property == null || !property.isAvailable(bookDate)) {
            throw new IllegalArgumentException("房产ID:" + propertyId + " 不存在或指定日期已被预订");
        }
    }
    // 校验通过,执行预订
    for (Long propertyId : propertyIds) {
        Property property = RentalSystemContext.allPropertyMap.get(propertyId);
        property.setOccupied(bookDate, true);
        // 可补充生成预订记录、关联到客户的预订列表等逻辑
    }
    return true;
}

现有代码优化提示

你当前的Hotel类用数组存储所有房型和数量的设计不合理,因为每个房间都是独立的可预订单元,建议把roomType改为单个字符串属性,每个Hotel实例对应一间具体的酒店客房,和公寓、民宿的实例粒度保持一致,后续预订逻辑不需要做特殊适配。

内容的提问来源于stack exchange,提问作者Dionisius Pratama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 03:09:02