研磨设计模式day09原型模式

目录

场景

代码实现

有何问题

解决方案

代码改造 

模式讲解

原型与new

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

浅度克隆和深度克隆

原型模式的优缺点

思考

何时选用?

相关模式 


场景

代码实现

定义订单接口 

package com.zsp.bike.day08原型模式;

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

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

个人订单实现

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;
    }



}

企业订单实现

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 +
                '}';
    }
}

通用的订单处理

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);
        
    }
}











客户端使用

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.在订单接口里面写一个克隆自己的方法

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;这么做客户端获取的都是同一个实例,都是指向同一个内存空间的,对克隆出来的对象实例进行修改会影响到原型对象实例。

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

个人订单对象修改

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;
    }



}

 企业订单修改

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 +
                '}';
    }
}

 处理订单的业务对象修改

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

浅度克隆和深度克隆

 

原型模式的优缺点

思考

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

创建型模式

何时选用?

相关模式 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/91015.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机msvcp120.dll丢失的解决方法,非常靠谱的三个解决方法

今天,我将为大家分享一个关于电脑报错msvcp120.dll解决方法的话题。在日常生活中,我们可能会遇到这样的问题:电脑突然出现“程序无法正常运行”的提示,然后要求我们重新安装某个软件或者升级系统。这时候,我们很可能会…

【C++】做一个飞机空战小游戏(十一)——游戏过关、通关、结束的设置

[导读]本系列博文内容链接如下: 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动【C】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C】做一个飞…

函数的参数传递和返回值-PHP8知识详解

本文学习的是《php8知识详解》中的《函数的参数传递和返回值》。主要包括:向函数传递参数值、向函数传递参数引用、函数的返回值。 1、向函数传递参数值 函数是一段封闭的程序,有时候,程序员需要向函数传递一些数据进行操作。可以接受传入参…

Docker容器与虚拟化技术:Gitlab账户注册

目录 一、实验 1.gitlab 一、实验 1.gitlab (1) 概念 GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的Web服务。 (2)官网 The DevSecOps Platform | GitLab (3&#…

算法笔记:KD树

1 引入原因 K近邻算法需要在整个数据集中搜索和测试数据x最近的k个点,如果一一计算,然后再排序,开销过大 引入KD树的作用就是对KNN搜索和排序的耗时进行改进 2 KD树 2.1 主体思路 以空间换时间,利用训练样本集中的样本点&…

图神经网络与分子表征:番外——基组选择

学过高斯软件的人都知道,我们在撰写输入文件 gjf 时需要准备输入【泛函】和【基组】这两个关键词。 【泛函】敲定计算方法,【基组】则类似格点积分中的密度,与计算精度密切相关。 部分研究人员借用高斯中的一系列基组去包装输入几何信息&am…

Linux线程 --- 生产者消费者模型(C语言)

在学习完线程相关的概念之后,本节来认识一下Linux多线程相关的一个重要模型----“ 生产者消费者模型” 本文参考: Linux多线程生产者与消费者_红娃子的博客-CSDN博客 Linux多线程——生产者消费者模型_linux多线程生产者与消费者_两片空白的博客-CSDN博客…

Discuz!论坛发帖标题字数限制80字符可以修改吗?修改发帖标题字数的方法

Discuz!论坛发帖标题字数限制80字符修改方法 1.数据库修改2.修改JS验证字符数文件3.修改模板中写死的字符限制数4.修改函数验证文件5.修改语言包文件6.更新缓存 Discuz X3.4论坛网站帖子标题字数限制80字符,当我们想使用长标题的时候就得一删再删,实在是…

JAVA switch case 穿透问题

1,前提 其实开发中很少会用到switch ,一般更倾向于if-else, 但是最近接手的项目,前人写的代码都用switch , 但是我一直以来对switch 的理解就跟if一样, 然后项目运用的时候才发现这玩意居然还有穿透问题 …

nginx(七十八)nginx配置http2

一 ngx_http_v2模块 1、本文不讲解HTTP2的知识2、只讲解nginx中如何配置HTTP2 ① 前置条件 1、openssl的版本必须在1.0.2e及以上2、开启https加密,目前http2.0只支持开启了https的网站编译选项:--with-http_ssl_module --with-http_v2_module 特点&#xff1a…

[管理与领导-51]:IT基层管理者 - 8项核心技能 - 6 - 流程

前言: 管理者存在的价值就是制定目标,即目标管理、通过团队(他人)拿到结果。 要想通过他人拿到结果: (1)目标:制定符合SMART原则的符合业务需求的目标,团队跳一跳就可以…

Vue3 [Day11]

Vue3的优势 create-vue搭建Vue3项目 node -v npm init vuelatest npm installVue3项目目录和关键文件 Vetur插件是Vue2的 Volarr插件是Vue3的 main.js import ./assets/main.css// new Vue() 创建一个应用实例 > createApp() // createRouter() createStore() // 将创建实…

基于JAYA算法优化的BP神经网络(预测应用) - 附代码

基于JAYA算法优化的BP神经网络(预测应用) - 附代码 文章目录 基于JAYA算法优化的BP神经网络(预测应用) - 附代码1.数据介绍2.JAYA优化BP神经网络2.1 BP神经网络参数设置2.2 JAYA算法应用 4.测试结果:5.Matlab代码 摘要…

容器技术,1. Docker,2. Kubernetes(K8s):

目录 容器技术 1. Docker: 2. Kubernetes(K8s): Docker和Kubernetes 容器的主要应用场景有哪些? 容器技术 有效的将单个操作系统的资源划分到孤立的组中,以便更好的在孤立的组之间平衡有冲突的资源使…

Kotlin协程flow发送时间间隔debounce

Kotlin协程flow发送时间间隔debounce debounce的作用是让连续发射的数据之间间隔起来。典型的应用场景是搜索引擎里面的关键词输入,当用户输入字符时候,有时候,并不希望用户每输入任何一个单字就触发一次后台真正的查询,而是希望…

《Dive into Deep Learning》

《Dive into Deep Learning》:https://d2l.ai/ Interactive deep learning book with code, math, and discussionsImplemented with PyTorch, NumPy/MXNet, JAX, and TensorFlowAdopted at 500 universities from 70 countries 《动手学深度学习》中文版&#xff1…

深度学习10:Attention 机制

目录 Attention 的本质是什么 Attention 的3大优点 Attention 的原理 Attention 的 N 种类型 Attention 的本质是什么 Attention(注意力)机制如果浅层的理解,跟他的名字非常匹配。他的核心逻辑就是「从关注全部到关注重点」。 Attention…

基于FPGA的Lorenz混沌系统verilog开发,含testbench和matlab辅助测试程序

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 将vivado的仿真结果导入到matlab显示三维混沌效果: 2.算法运行软件版本 vivado2019.2 matlab2022a 3.部分核心程序 testbench如下所…

Docker安装ES+kibana8.9.1

参考:基于Docker安装Elasticsearch【保姆级教程、内含图解】_docker elasticsearch_Acloasia的博客-CSDN博客 创建网络 docker network create es-net 基于Docker安装Elasticsearch 拉取镜像 docker pull elasticsearch:8.9.1 挂载文件 mkdir -p /usr/local/e…

stm32之USART(总结)

串行通信 UART串口内部结构示意图 普中科技的详细介绍 中断知识补充 代码 #ifndef __USART_H #define __USART_H #include "stdio.h" #include "stm32f10x_usart.h" #define USART1_REC_LEN 200 //定义最大接收字节数 200extern u8 USART1_RX_BUF[US…