Skip to content

目的

事务脚本模式通过过程组织业务逻辑,其中每个过程处理来自表现层的单个请求。

解释

现实中的例子

您需要创建一个酒店房间预订系统。由于需求非常简单,我们打算在这里使用事务脚本模式。

直白的说

事务脚本将业务逻辑组织成系统需要执行的事务。

代码样例

Hotel 类负责预定和取消房间预定

java
@Slf4j
public class Hotel {

  private final HotelDaoImpl hotelDao;

  public Hotel(HotelDaoImpl hotelDao) {
    this.hotelDao = hotelDao;
  }

  public void bookRoom(int roomNumber) throws Exception {

    Optional<Room> room = hotelDao.getById(roomNumber);

    if (room.isEmpty()) {
      throw new Exception("Room number: " + roomNumber + " does not exist");
    } else {
      if (room.get().isBooked()) {
        throw new Exception("Room already booked!");
      } else {
        Room updateRoomBooking = room.get();
        updateRoomBooking.setBooked(true);
        hotelDao.update(updateRoomBooking);
      }
    }
  }

  public void cancelRoomBooking(int roomNumber) throws Exception {

    Optional<Room> room = hotelDao.getById(roomNumber);

    if (room.isEmpty()) {
      throw new Exception("Room number: " + roomNumber + " does not exist");
    } else {
      if (room.get().isBooked()) {
        Room updateRoomBooking = room.get();
        updateRoomBooking.setBooked(false);
        int refundAmount = updateRoomBooking.getPrice();
        hotelDao.update(updateRoomBooking);

        LOGGER.info("Booking cancelled for room number: " + roomNumber);
        LOGGER.info(refundAmount + " is refunded");
      } else {
        throw new Exception("No booking for the room exists");
      }
    }
  }
}

“Hotel”类有两种方法,分别用于预订和取消预定房间。它们分别处理系统中的单个事务,从而让“Hotel”类实现事务脚本模式。

“bookRoom”方法整合了所有必须的步骤,比如检查房间是否已经预订,如果没有预订,则预定房间并且使用DAO层的方法更新数据库。

“cancelRoom”方法整合了一些步骤,比如检查房间是否已预订,如果已预订,则计算退款金额并使用DAO层的方法更新数据库。

类图

alt text

适用性

当应用程序只有少量逻辑并且该逻辑将来不会被扩展时,使用事务脚本模式。

后果

  • 当业务逻辑更复杂的时候就变得更难去保持事务脚本的良好设计
  • 不同事务脚本之间可能会有代码重复
  • 通常不容易重构事务脚本到其他其他Domain模型

相关模式

  • Domain Model
  • Table Module
  • Service Layer

鸣谢