研磨设计模式day09原型模式

目录

场景

代码实现

有何问题

解决方案

代码改造

模式讲解

原型与new

原型实例与克隆出来的实例

浅度克隆和深度克隆

原型模式的优缺点

思考

何时选用?

相关模式


场景

代码实现

定义订单接口

java 复制代码
package com.zsp.bike.day08原型模式;

/**
 * 订单的接口
 */
public interface OrderApi {
    /**
     * 获取订单数量
     * @return
     */
    public int getOrderProductNum();

    /**
     * 设置订单产品数量
     * @param num 订单产品数量
     */
    public void setOrderProductNum(int num);
}

个人订单实现

java 复制代码
package com.zsp.bike.day08原型模式;

/**
 * 个人订单对象
 */
public class PersonalOrder implements OrderApi{
    /**
     * 订购人员姓名
     */
    private String customerName;

    /**
     * 产品编号
     */
    private String productId;

    /**
     * 订单产品数量
     */
    private int orderProductNum = 0;

    @Override
    public int getOrderProductNum() {
        return this.orderProductNum;
    }

    @Override
    public void setOrderProductNum(int num) {
        this.orderProductNum = num;
    }


    @Override
    public String toString() {
        return "PersonalOrder{" +
                "customerName='" + customerName + '\'' +
                ", productId='" + productId + '\'' +
                ", orderProductNum=" + orderProductNum +
                '}';
    }

    public String getCustomerName() {
        return customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }

    public String getProductId() {
        return productId;
    }

    public void setProductId(String productId) {
        this.productId = productId;
    }



}

企业订单实现

java 复制代码
package com.zsp.bike.day08原型模式;

/**
 * 企业订单对象
 */
public class EnterpriseOrder implements OrderApi{
    /**
     * 企业名称
     */
    private String enterpriseName;

    /**
     * 产品编号
     */
    private String productId;

    /**
     * 订单产品数量
     */
    private int orderProductNum = 0;

    @Override
    public int getOrderProductNum() {
        return this.orderProductNum;
    }

    @Override
    public void setOrderProductNum(int num) {
        this.orderProductNum = num;
    }


    public String getEnterpriseName() {
        return enterpriseName;
    }

    public void setEnterpriseName(String enterpriseName) {
        this.enterpriseName = enterpriseName;
    }

    public String getProductId() {
        return productId;
    }

    public void setProductId(String productId) {
        this.productId = productId;
    }

    @Override
    public String toString() {
        return "EnterpriseOrder{" +
                "enterpriseName='" + enterpriseName + '\'' +
                ", productId='" + productId + '\'' +
                ", orderProductNum=" + orderProductNum +
                '}';
    }
}

通用的订单处理

java 复制代码
package com.zsp.bike.day08原型模式;

/**
 * 处理订单的业务对象
 */
public class OrderBusiness {

    /**
     * 创建订单的方法
     * @param order 订单的接口对象
     */
    public void saveOrder(OrderApi order){
        // 业务要求,当订单数量大于1000,把订单分成两份订单

        //1.判断产品数量是否大于1000
        while (order.getOrderProductNum() > 1000){
        // 2.如果大于,还需要继续拆分
            // 2.1 再新建一份订单,跟传入的订单除了数量不一样外,其他都相同
            OrderApi newOrder = null;
            
            // 如果属于个人订单
            if (order instanceof PersonalOrder){
                // 创建相应的新的订单对象
                PersonalOrder p2 = new PersonalOrder();
                // 然后进行赋值,但是产品数量为1000
                PersonalOrder p1 = (PersonalOrder)order;
                p2.setCustomerName(p1.getCustomerName());
                p2.setProductId(p1.getProductId());
                p2.setOrderProductNum(1000);
                // 再设置给newOrder
                newOrder = p2;
            // 如果属于企业订单    
            }else if(order instanceof EnterpriseOrder){
                // 创建相应的订单对象
                EnterpriseOrder e2 = new EnterpriseOrder();
                // 然后进行赋值,但是产品数量为1000
                EnterpriseOrder e1 = (EnterpriseOrder)order;
                e2.setEnterpriseName(e1.getEnterpriseName());
                e2.setProductId(e1.getProductId());
                e2.setOrderProductNum(1000);
                // 再设置给newOrder
                newOrder = e2;
            }
            // 2.2 原来的订单保留,把数量设置成减少1000
            order.setOrderProductNum(order.getOrderProductNum() - 1000);
            // 然后是业务功能处理,省略了,打印输出看一下
            System.out.println("拆分生成订单==" + newOrder);
        }
        
        //3.不超过1000,那就直接业务功能处理,省略了,打印输出看一下
        System.out.println("订单==" + order);
        
    }
}

客户端使用

java 复制代码
package com.zsp.bike.day08原型模式;

public class Client {
    public static void main(String[] args) {
        // 创建订单对象,这里为了演示,直接new了
        PersonalOrder op = new PersonalOrder();
        // 设置订单数据
        op.setOrderProductNum(2925);
        op.setProductId("P0001");
        op.setCustomerName("张三");

        // 这里获取业务处理的类,也直接new了
        OrderBusiness ob = new OrderBusiness();
        ob.saveOrder(op);
    }
}

有何问题

简述:

1.订单处理的对象太过依赖与具体实现,划分的很细。

2.如果要增加一种新类型订单,就要增加新的订单类型支持,就要修改这个订单处理逻辑。

解决方案

原型模式

定义:

解决思路:

代码改造

1.在订单接口里面写一个克隆自己的方法

java 复制代码
package com.zsp.bike.day08原型模式;

/**
 * 订单的接口
 */
public interface OrderApi {
    /**
     * 获取订单数量
     * @return
     */
    public int getOrderProductNum();

    /**
     * 设置订单产品数量
     * @param num 订单产品数量
     */
    public void setOrderProductNum(int num);

    /**
     * 克隆方法
     * @return 订单原型的实例
     */
    public OrderApi cloneOrder();
}

2.如何克隆?

千万不能return this;这么做客户端获取的都是同一个实例,都是指向同一个内存空间的,对克隆出来的对象实例进行修改会影响到原型对象实例。

应该新建一个实例,把所有属性的值复制到新实例中。

个人订单对象修改

java 复制代码
package com.zsp.bike.day08原型模式;

/**
 * 个人订单对象
 */
public class PersonalOrder implements OrderApi{
    /**
     * 订购人员姓名
     */
    private String customerName;

    /**
     * 产品编号
     */
    private String productId;

    /**
     * 订单产品数量
     */
    private int orderProductNum = 0;

    @Override
    public int getOrderProductNum() {
        return this.orderProductNum;
    }

    @Override
    public void setOrderProductNum(int num) {
        this.orderProductNum = num;
    }

    @Override
    public OrderApi cloneOrder() {
        PersonalOrder order = new PersonalOrder();
        order.setOrderProductNum(this.orderProductNum);
        order.setCustomerName(this.customerName);
        order.setProductId(this.productId);
        return order;
    }


    @Override
    public String toString() {
        return "PersonalOrder{" +
                "customerName='" + customerName + '\'' +
                ", productId='" + productId + '\'' +
                ", orderProductNum=" + orderProductNum +
                '}';
    }

    public String getCustomerName() {
        return customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }

    public String getProductId() {
        return productId;
    }

    public void setProductId(String productId) {
        this.productId = productId;
    }



}

企业订单修改

java 复制代码
package com.zsp.bike.day08原型模式;

/**
 * 企业订单对象
 */
public class EnterpriseOrder implements OrderApi{
    /**
     * 企业名称
     */
    private String enterpriseName;

    /**
     * 产品编号
     */
    private String productId;

    /**
     * 订单产品数量
     */
    private int orderProductNum = 0;

    @Override
    public int getOrderProductNum() {
        return this.orderProductNum;
    }

    @Override
    public void setOrderProductNum(int num) {
        this.orderProductNum = num;
    }

    @Override
    public OrderApi cloneOrder() {
        EnterpriseOrder order = new EnterpriseOrder();
        order.setOrderProductNum(this.orderProductNum);
        order.setEnterpriseName(this.enterpriseName);
        order.setProductId(this.productId);
        return order;
    }


    public String getEnterpriseName() {
        return enterpriseName;
    }

    public void setEnterpriseName(String enterpriseName) {
        this.enterpriseName = enterpriseName;
    }

    public String getProductId() {
        return productId;
    }

    public void setProductId(String productId) {
        this.productId = productId;
    }

    @Override
    public String toString() {
        return "EnterpriseOrder{" +
                "enterpriseName='" + enterpriseName + '\'' +
                ", productId='" + productId + '\'' +
                ", orderProductNum=" + orderProductNum +
                '}';
    }
}

处理订单的业务对象修改

java 复制代码
package com.zsp.bike.day08原型模式;

/**
 * 处理订单的业务对象
 */
public class OrderBusiness {

    /**
     * 创建订单的方法
     * @param order 订单的接口对象
     */
    public void saveOrder(OrderApi order){
        // 业务要求,当订单数量大于1000,把订单分成两份订单

        //1.判断产品数量是否大于1000
        while (order.getOrderProductNum() > 1000){
        // 2.如果大于,还需要继续拆分
            // 2.1 再新建一份订单,跟传入的订单除了数量不一样外,其他都相同
            OrderApi newOrder = order.cloneOrder();
            // 然后进行赋值,产品数量为1000
            newOrder.setOrderProductNum(1000);
            // 2.2 原来的订单保留,把数量设置成减少1000
            order.setOrderProductNum(order.getOrderProductNum() - 1000);
            // 然后是业务功能处理,省略了,打印输出看一下
            System.out.println("拆分生成订单==" + newOrder);
        }

        //3.不超过1000,那就直接业务功能处理,省略了,打印输出看一下
        System.out.println("订单==" + order);

    }
}

通过

用订单的原型实例来指定对象的种类,通过克隆这个原型实例来创建出了一个新的对象实例。

模式讲解

原型模式的功能:

1.通过克隆来创建新的对象实例

2.为克隆出来的新的对象实例复制原型实例属性的值

原型与new

与new不同点在于,new出来的属性是没有值或者只有默认值,克隆出来的实例一般是有值的,它的值就是原型实例的属性的值。

原型实例与克隆出来的实例

克隆完成后,与原型实例是没有关联的,克隆出来的实例属性值发生变化不会影响原型实例。根源在于不是return this; 是复制的,是指向不同内存空间的

需要克隆的类,可以实现java.lang.Cloneable

浅度克隆和深度克隆

原型模式的优缺点

思考

原型模式的本质:克隆生成对象

创建型模式

何时选用?

相关模式

相关推荐
reddingtons2 小时前
【游戏宣发】PS “生成式扩展”流,30秒无损适配全渠道KV
游戏·设计模式·新媒体运营·prompt·aigc·教育电商·游戏美术
李慕婉学姐3 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
奋进的芋圆4 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin5 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model20055 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉5 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国5 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_941882485 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈6 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_996 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc