原型模式(Prototype Pattern)

43 阅读3分钟

原型模式(Prototype Pattern)是一种创建型设计模式,它允许通过复制现有对象来创建新对象,而无需知道具体类的信息。

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.io.Serial;
import java.io.Serializable;

// 地址类
@Setter
@Getter
@ToString
public class Address implements Cloneable, Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    private String street;
    private String city;
    private String state;
    private String zipCode;

    public Address() {
    }

    public Address(String street, String city, String state, String zipCode) {
        this.street = street;
        this.city = city;
        this.state = state;
        this.zipCode = zipCode;
    }

    @Override
    public Address clone() throws CloneNotSupportedException {
        return (Address) super.clone();
    }

}
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.io.Serial;
import java.io.Serializable;

// 订单项类
@Setter
@Getter
@ToString
public class OrderItem implements Cloneable, Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    private String productId;
    private String productName;
    private int quantity;
    private double price;

    public OrderItem() {
    }

    public OrderItem(String productId, String productName, int quantity, double price) {
        this.productId = productId;
        this.productName = productName;
        this.quantity = quantity;
        this.price = price;
    }

    @Override
    public OrderItem clone() throws CloneNotSupportedException {
        return (OrderItem) super.clone();
    }

}
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.*;

// 订单类 - 实现浅克隆
@Setter
@Getter
@ToString
public class Order implements Cloneable {
    // getter和setter方法
    private String orderId;
    private String customerName;
    private String customerEmail;
    private List<OrderItem> items;
    private Address shippingAddress;
    private Date orderDate;
    private OrderStatus status;

    public Order() {
        this.items = new ArrayList<>();
    }

    public Order(String orderId, String customerName, String customerEmail) {
        this.orderId = orderId;
        this.customerName = customerName;
        this.customerEmail = customerEmail;
        this.items = new ArrayList<>();
        this.orderDate = new Date();
        this.status = OrderStatus.PENDING;
    }

    // 添加订单项
    public void addItem(OrderItem item) {
        this.items.add(item);
    }

    // 浅克隆实现
    @Override
    public Order clone() throws CloneNotSupportedException {
        Order clonedOrder = (Order) super.clone();
        // 浅克隆:只复制items列表的引用,不复制列表中的元素
        clonedOrder.items = new ArrayList<>(this.items);
        return clonedOrder;
    }

}
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

// 使用Hutool实现深克隆的订单类
@Setter
@Getter
@ToString
public class DeepCloneOrder implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    private String orderId;
    private String customerName;
    private String customerEmail;
    private List<OrderItem> items;
    private Address shippingAddress;
    private Date orderDate;
    private OrderStatus status;

    public DeepCloneOrder() {
        this.items = new ArrayList<>();
    }

    public DeepCloneOrder(String orderId, String customerName, String customerEmail) {
        this.orderId = orderId;
        this.customerName = customerName;
        this.customerEmail = customerEmail;
        this.items = new ArrayList<>();
        this.orderDate = new Date();
        this.status = OrderStatus.PENDING;
    }

    // 添加订单项
    public void addItem(OrderItem item) {
        this.items.add(item);
    }

}
// 订单状态枚举
public enum OrderStatus {

    PENDING,     // 待处理
    CONFIRMED,   // 已确认
    SHIPPED,     // 已发货
    DELIVERED,   // 已送达
    CANCELLED    // 已取消
}
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;

// 客户端测试代码
@Slf4j
public class PrototypePatternDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        // 创建原始订单
        Order originalOrder = new Order("ORD001", "张三", "zhangsan@example.com");

        // 添加订单项
        originalOrder.addItem(new OrderItem("P001", "iPhone 14", 1, 5999.0));
        originalOrder.addItem(new OrderItem("P002", "AirPods Pro", 2, 1999.0));

        // 设置收货地址
        Address address = new Address("中山路123号", "广州市", "广东省", "510000");
        originalOrder.setShippingAddress(address);

        log.info("=== 原始订单 ===");
        log.info(originalOrder.toString());

        // 浅克隆示例
        shallowCloneExample(originalOrder);

        log.info("========================================");

        // 深克隆示例(使用Hutool)
        deepCloneExample(originalOrder);
    }

    // 浅克隆示例
    public static void shallowCloneExample(Order originalOrder) throws CloneNotSupportedException {
        log.info("=== 浅克隆示例 ===");

        // 克隆订单
        Order clonedOrder = originalOrder.clone();

        // 修改克隆订单的信息(这些是基本类型或新对象,不会影响原始订单)
        clonedOrder.setOrderId("ORD002");
        clonedOrder.setCustomerName("李四");
        clonedOrder.setCustomerEmail("lisi@example.com");

        // 修改订单项(演示浅克隆的问题)
        if (!clonedOrder.getItems().isEmpty()) {
            OrderItem firstItem = clonedOrder.getItems().get(0);
            firstItem.setProductName("iPhone 14 Pro"); // 修改克隆订单的第一个商品名
        }

        log.info("原始订单第一个商品: " + originalOrder.getItems().get(0).getProductName());
        log.info("克隆订单第一个商品: " + clonedOrder.getItems().get(0).getProductName());
        log.info("注意:由于是浅克隆,修改克隆订单的商品名也影响了原始订单!");

        log.info("原始订单: " + originalOrder.getOrderId() + " - " + originalOrder.getCustomerName());
        log.info("克隆订单: " + clonedOrder.getOrderId() + " - " + clonedOrder.getCustomerName());
        log.info("注意:订单ID和客户名是独立的,修改克隆订单不会影响原始订单的这些属性");
    }

    // 深克隆示例(使用Hutool)
    public static void deepCloneExample(Order originalOrder) {
        log.info("=== 深克隆示例(使用Hutool)===");

        // 创建用于深克隆的订单对象
        DeepCloneOrder deepOriginalOrder = new DeepCloneOrder(
                originalOrder.getOrderId(),
                originalOrder.getCustomerName(),
                originalOrder.getCustomerEmail()
        );

        // 复制订单项
        for (OrderItem item : originalOrder.getItems()) {
            deepOriginalOrder.addItem(new OrderItem(
                    item.getProductId(),
                    item.getProductName(),
                    item.getQuantity(),
                    item.getPrice()
            ));
        }

        // 复制地址
        Address originalAddress = originalOrder.getShippingAddress();
        if (originalAddress != null) {
            deepOriginalOrder.setShippingAddress(new Address(
                    originalAddress.getStreet(),
                    originalAddress.getCity(),
                    originalAddress.getState(),
                    originalAddress.getZipCode()
            ));
        }

        // 使用Hutool进行深克隆,前提是对象必须实现Serializable接口。
        DeepCloneOrder deepClonedOrder = ObjectUtil.cloneByStream(deepOriginalOrder);

        // 修改克隆订单的信息
        deepClonedOrder.setOrderId("ORD003");
        deepClonedOrder.setCustomerName("王五");
        deepClonedOrder.setCustomerEmail("wangwu@example.com");

        // 修改订单项(演示深克隆的效果)
        if (!deepClonedOrder.getItems().isEmpty()) {
            OrderItem firstItem = deepClonedOrder.getItems().get(0);
            firstItem.setProductName("iPhone 14 Pro Max"); // 修改克隆订单的第一个商品名
        }

        log.info("原始订单第一个商品: " + deepOriginalOrder.getItems().get(0).getProductName());
        log.info("深克隆订单第一个商品: " + deepClonedOrder.getItems().get(0).getProductName());
        log.info("注意:由于是深克隆,修改克隆订单的商品名不会影响原始订单!");

        log.info("原始订单: " + deepOriginalOrder.getOrderId() + " - " + deepOriginalOrder.getCustomerName());
        log.info("深克隆订单: " + deepClonedOrder.getOrderId() + " - " + deepClonedOrder.getCustomerName());
    }
}