【设计模式】创建型模式——原型模式

原型模式

一、定义

原型模式是一种创建型设计模式。能够复制已有对象, 而又无需使代码依赖它们所属的类。

二、问题

有一个订单系统,当订单中的货品数量大于1000时,那么该系统就会分拆成两个订单,如果还大于1000再拆分……
订单:id,货物名称,数量
货物:id,货物名称

三、解决方案

我们就可以使用克隆来完成对订单的复制。
创建一系列不同类型的对象并不同的方式对其进行配置。 如果所需对象与预先配置的对象相同, 那么你只需克隆原型即可, 无需新建一个对象。
支持克隆的对象即为原型(该问题中为订单)

注意:克隆时需要注意深浅拷贝的问题!
浅拷贝:拷贝基本数据类型 如 id,数量
深拷贝:拷贝引用数据类型 如 货物

四、代码实现

1、原型 (Prototype) 接口将对克隆方法进行声明。 在绝大多数情况下, 其中只会有一个名为 clone克隆的方法。

这里使用的是Java自带的克隆接口

package java.lang;

/**
 * A class implements the <code>Cloneable</code> interface to
 * indicate to the {@link java.lang.Object#clone()} method that it
 * is legal for that method to make a
 * field-for-field copy of instances of that class.
 * <p>
 * Invoking Object's clone method on an instance that does not implement the
 * <code>Cloneable</code> interface results in the exception
 * <code>CloneNotSupportedException</code> being thrown.
 * <p>
 * By convention, classes that implement this interface should override
 * <tt>Object.clone</tt> (which is protected) with a public method.
 * See {@link java.lang.Object#clone()} for details on overriding this
 * method.
 * <p>
 * Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
 * Therefore, it is not possible to clone an object merely by virtue of the
 * fact that it implements this interface.  Even if the clone method is invoked
 * reflectively, there is no guarantee that it will succeed.
 *
 * @author  unascribed
 * @see     java.lang.CloneNotSupportedException
 * @see     java.lang.Object#clone()
 * @since   JDK1.0
 */
public interface Cloneable {
    
    
}

2、具体原型 (Concrete Prototype) 类将实现克隆方法。

package com.atmae.prototype;

/**
 * @Author: Mae
 * @Date: 2022/4/13
 * @Time: 11:57
 * @Description:
 */
public class Order implements Cloneable {
    
    

    public Order(Long id, Product product, Integer num) {
    
    
        this.id = id;
        this.product = product;
        this.num = num;
    }

    /**
     * 订单id号
     */
    private Long id;
    /**
     * 订单产品
     */
    private Product product;
    /**
     * 产品数量
     */
    private Integer num;


    public Long getId() {
    
    
        return id;
    }

    public void setId(Long id) {
    
    
        this.id = id;
    }

    public Product getProduct() {
    
    
        return product;
    }

    public void setProduct(Product product) {
    
    
        this.product = product;
    }

    public Integer getNum() {
    
    
        return num;
    }

    public void setNum(Integer num) {
    
    
        this.num = num;
    }

    @Override
    public String toString() {
    
    
        return "Order{" +
                "id=" + id +
                ", product=" + product +
                ", num=" + num +
                '}'+'\n';
    }

    /**
     * 深拷贝
     * @return 订单对象
     * @throws CloneNotSupportedException 克隆?
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
    
    
        Order order = (Order) super.clone();
        order.product= (Product) this.product.clone();
        return order;
    }
}

3、客户端

package com.atmae.prototype;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: Mae
 * @Date: 2022/4/13
 * @Time: 13:01
 * @Description: 客户端
 */
public class Client {
    
    
    public static void main(String[] args) throws CloneNotSupportedException {
    
    
        Product product = new Product("面包", 10001L);
        Order order = new Order(10000L, product, 6600);
        List<Order> orders = new ArrayList<>();
        int num=1;
        while (order.getNum() > 1000) {
    
    
            Order o = (Order) order.clone();
            o.setNum(1000);
            o.setId(order.getId()+num);
            order.setNum(order.getNum() - 1000);
            orders.add(o);
            num++;
        }
        orders.add(order);
        System.out.println(orders);
    }
}

在这里插入图片描述

五、UML图

在这里插入图片描述

六、原型模式适用场景

  • 需要复制一些对象, 同时又希望代码独立于这些对象所属的具体类

七、总结

优点

  • 可以克隆对象, 而无需与它们所属的具体类相耦合。
  • 可以克隆预生成原型, 避免反复运行初始化代码。
  • 可以更方便地生成复杂对象。
  • 可以用继承以外的方式来处理复杂对象的不同配置。

缺点

  • 如果克隆引用数据类型,需要递归克隆

八、与其他模式的比较

  • 与工厂方法模式
    原型并不基于继承, 因此没有继承的缺点。 另一方面, 原型需要对被复制对象进行复杂的初始化。
    工厂方法基于继承, 但是它不需要初始化步骤。
    原型可以起到工厂模式的效果。

猜你喜欢

转载自blog.csdn.net/weixin_51799151/article/details/124145859