研磨设计模式day09原型模式

news2024/12/26 23:15:53

目录

场景

代码实现

有何问题

解决方案

代码改造 

模式讲解

原型与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

浅度克隆和深度克隆

 

原型模式的优缺点

思考

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

创建型模式

何时选用?

相关模式 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据时代的软件开发实践:利用云计算和AI赋能创新

文章目录 云计算的赋能弹性资源管理远程协作与分布式开发持续集成和持续交付成本效益 人工智能的赋能数据驱动的决策自动化智能预测和优化自适应系统 创新的实践方法数据驱动的创新智能化产品开放式创新迭代和反馈 🎈个人主页:程序员 小侯 🎐…

开源的安全性:挑战与机会

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

Spring和mybatis整合

一、Spring整合MyBatis 1. 导入pom依赖 1.1 添加spring相关依赖(5.0.2.RELEASE) spring-core spring-beans spring-context spring-orm spring-tx spring-aspects spring-web 1.2 添加mybatis相关依赖 mybatis核心:mybatis(3.4.5) Mybatis分页:pagehel…

基于Python的小区监控图像拼接系统设计与实现【源码+论文+演示视频+包运行成功】

博主介绍:✌csdn特邀作者、博客专家、java领域优质创作者、博客之星,擅长Java、微信小程序、Python、Android等技术,专注于Java、Python等技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 …

华为云渲染实践

// 编者按:云计算与网络基础设施发展为云端渲染提供了更好的发展机会,华为云随之长期在自研图形渲染引擎、工业领域渲染和AI加速渲染三大方向进行云渲染方面的探索与研究。本次LiveVideoStackCon 2023上海站邀请了来自华为云的陈普,为大家分…

研磨设计模式day11代理模式

目录 场景 代码实现 ​编辑 解析 定义 代理模式调用示意图 代理模式的特点 本质 ​编辑何时选用 场景 我有一个订单类,包含订单数、用户名和商品名,有一个订单接口包含了对订单类的getter和setter 现在有一个需求,a创建的订单只…

位运算(包括OR,AND,XOR,NOR,NAND,XNOR,以及0xFF等常见应用)

目录 ​编辑 1、按位与操作 2、按位或操作 3、取反运算 4、异或运算 不同为1,相同为0 ​编辑 5、左移运算 6、右移运算 常见用途: C语言位运算讲解: 位运算(包括OR,AND,XOR,NOR,NAND,XNOR,以及&0xFF等常…

React 项目中引入msal验证以及部分报错处理

功能实现 如何在React 项目中引入msal身份验证, 微软在官网有提供文档支持,文档包含示例和具体使用的教程,地址如下: https://learn.microsoft.com/zh-cn/azure/active-directory/develop/tutorial-v2-nodejs-webapp-msal 照着文…

ppt转pdf免费的工具哪个好用?ppt在线转pdf的方法分享

在工作和学习中,将PPT文件转换为PDF格式具有重要意义。PDF文件的大小较小,适用于各种平台和设备,保持了原始文件的内容和格式,具有广泛的可读性和兼容性。那么小编就来为大家详细地说一说“ppt转pdf免费的工具哪个好用?ppt在线转…

Pycharm链接远程mysql报错

Pycharm链接远程mysql配置及相应报错如下: 解决方法: 去服务器确认Mysql版本号: 我的Mysql为5.7.43,此时Pycharm mysql驱动为8.0版本,不匹配,所以需要根据实际的版本选择对应的驱动;选择对应的版…

TinyVue - 华为云 OpenTiny 出品的企业级前端 UI 组件库,免费开源,同时支持 Vue2 / Vue3,自带 TinyPro 中后台管理系统

华为最新发布的前端 UI 组件库,支持 PC 和移动端,自带了 admin 后台系统,完成度很高,web 项目开发又多一个选择。 关于 OpenTiny 和 TinyVue 在上个月结束的华为开发者大会2023上,官方正式进行发布了 OpenTiny&#…

uniapp使用sqlite 数据库

uniapp使用sqlite 数据库 傻瓜式使用方式,按步骤,即可使用。 1.开启sqlite 在项目中manifest.json该文件中配置 2.封装数据库的调用方法 const sqlName "zmyalh" //定义的数据库名称 const sqlPath "_doc/zmyalh.db" //定义数…

【腾讯云 TDSQL-C Serverless 产品测评】- 云数据库之旅

“腾讯云 TDSQL-C 产品测评活动”是由腾讯云联合 CSDN 推出的针对数据库产品测评及产品体验活动,本次活动主要面向 TDSQL-C Serverless版。 本次参与活动可以涵盖不同技术层面的用户,可以针对TDSQL-C产品的自动弹性能力、自动启停能力、兼容性、安全、并…

EasyExcel自定义字段对象转换器支持转换实体和集合实体

文章目录 1. 实现ObjectConverter2. 使用3. 测试3.2 导出excel3.1 导入excel 1. 实现ObjectConverter package com.tophant.cloud.common.excel.converters;import cn.hutool.json.JSONUtil; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.…

CSS中如何实现多列布局?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 多列布局(Multi-column Layout)⭐ column-count⭐ column-width⭐ column-gap⭐ column-rule⭐ column-span⭐ 示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧…

多线程与高并发——并发编程(2)

文章目录 二、并发编程的三大特性1 原子性1.1 什么是原子性1.2 怎么保证原子性1.2.1 synchronized1.2.2 CAS1.2.3 Lock 锁1.2.4 ThreadLocal 2 可见性2.1 什么是可见性2.2 解决可见性的方式2.2.1 volatile2.2.2 synchronized2.2.3 Lock2.2.4 final 3 有序性3.1 什么是有序性3.2…

iOS HealthKit 介绍

文章目录 一、简介二、权限配置1. 在开发者账号中勾选HealthKit2. 在targets的capabilities中添加HealthKit。3. infoPlist需要配置权限 三、创建健康数据管理类1. 引入头文件2. 健康数据读写权限3. 检查权限4. 读取步数数据5. 写入健康数据 四、运行获取权限页面 一、简介 He…

Linux 下 Mysql 的使用(Ubuntu20.04)

文章目录 一、安装二、使用2.1 登录2.2 数据库操作2.2.1 创建数据库2.2.2 删除数据库2.2.3 创建数据表 参考文档 一、安装 Linux 下 Mysql 的安装非常简单,一个命令即可: sudo apt install mysql-server检查安装是否成功,输入: …

【KingSCADA】问题处理:记录KS历史报警查询异常

哈喽,大家好!我是雷工。 本篇记录KingSCADA的历史报警应用中的一个问题,及处理过程。 一、问题描述 最近客户遇到这么一个问题:当打开历史报警窗界面,自动加载的报警信息中有显示最近几天的报警信息,但当…

基于亚马逊云科技无服务器服务快速搭建电商平台——部署篇

受疫情影响消费者习惯发生改变,刺激了全球电商行业的快速发展。除了依托第三方电商平台将产品销售给消费者之外,企业通过品牌官网或者自有电商平台销售商品也是近几年电商领域快速发展的商业模式。独立站电商模式可以进行多方面、全渠道的互联网市场拓展…