研磨设计模式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

浅度克隆和深度克隆

原型模式的优缺点

思考

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

创建型模式

何时选用?

相关模式

相关推荐
_oP_i3 分钟前
Pinpoint 是一个开源的分布式追踪系统
java·分布式·开源
mmsx6 分钟前
android sqlite 数据库简单封装示例(java)
android·java·数据库
武子康31 分钟前
大数据-258 离线数仓 - Griffin架构 配置安装 Livy 架构设计 解压配置 Hadoop Hive
java·大数据·数据仓库·hive·hadoop·架构
豪宇刘2 小时前
MyBatis的面试题以及详细解答二
java·servlet·tomcat
秋恬意2 小时前
Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别
java·数据库·mybatis
FF在路上2 小时前
Knife4j调试实体类传参扁平化模式修改:default-flat-param-object: true
java·开发语言
真的很上进3 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
众拾达人3 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
皓木.3 小时前
Mybatis-Plus
java·开发语言
不良人天码星3 小时前
lombok插件不生效
java·开发语言·intellij-idea