热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

设计模式原型模式

目录概念编码实例浅克隆深克隆对于引用类型单独克隆序列化实现深克隆总结源码概念原型模式(PrototypePattern):使用原型实例指定创建对象的种类,并且通过克隆这些原型创建新

目录
  • 概念
  • 编码
    • 实例
    • 浅克隆
    • 深克隆
      • 对于引用类型单独克隆
      • 序列化实现深克隆
  • 总结
  • 源码


概念

  • 原型模式(Prototype Pattern):使用原型实例指定创建对象的种类,并且通过克隆这些原型创建新的对象

  • 原型模式是一种对象创建型模式

  • 原型模式最典型的例子就是孙悟空用猴毛复制出和自己一模一样的分身来,通过原型对象克隆出多个一模一样的对象就是原型模式




编码

实例



  • 通过原型模式实现销售管理系统中的客户类(Customer

  • Customer.java

/**
* @Description 客户
*/
public class Customer implements Cloneable {
private String name;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Customer{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
/**
* 重写克隆方法
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}


  • Java中通过实现Cloneable接口重写clone()方法来实现原型模式

  • Test.java

/**
* @Description 原型模式测试类
*/
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Customer customer = new Customer();
customer.setName("张三");
customer.setAddress("四川省成都市");
System.out.println(customer);
Customer customerClOne= (Customer) customer.clone();
customerClone.setAddress("浙江省杭州市");
System.out.println(customerClone);
}
}


  • 输出如下:

Customer{name='张三', address='四川省成都市'}
Customer{name='张三', address='浙江省杭州市'}


  • 通过克隆方法创建的对象是全新的对象,它们在内存中拥有新的地址




浅克隆



  • 如上例子,客户地址修改为Address

  • Customer.java

/**
* @Description 客户
*/
public class Customer implements Cloneable {
private String name;
private Address address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "Customer{" +
"name='" + name + '\'' +
", address=" + address +
'}';
}
/**
* 重写克隆方法
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}


  • Address.java

/**
* @Description 地址
*/
public class Address {
private String province;
private String city;
public Address(String province, String city) {
this.province = province;
this.city = city;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address{" +
"province='" + province + '\'' +
", city='" + city + '\'' +
'}';
}
}


  • Test.java

/**
* @Description 浅克隆测试类
*/
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Customer customer = new Customer();
customer.setName("张三");
customer.setAddress(new Address("四川省", "成都市"));
System.out.println(customer);
Customer customerClOne= (Customer) customer.clone();
System.out.println(customerClone);
System.out.println(customer == customerClone);
System.out.println("--------------");
customer.getAddress().setProvince("浙江省");
customer.getAddress().setCity("杭州市");
System.out.println(customer);
System.out.println(customerClone);
System.out.println(customer == customerClone);
}
}


  • 输出如下:

Customer{name='张三', address=Address{province='四川省', city='成都市'}}
Customer{name='张三', address=Address{province='四川省', city='成都市'}}
false
--------------
Customer{name='张三', address=Address{province='浙江省', city='杭州市'}}
Customer{name='张三', address=Address{province='浙江省', city='杭州市'}}
false


  • 可以发现,修改customercustomerClone的值也跟着修改了

  • Java语言中,数据类型分为值类型(基本数据类型)和引用类型,值类型包括intdoublebyte等简单数据类型,引用类型包括类、接口、数组等复杂类型,浅克隆与深克隆的区别在于是否支持引用类型的成员变量的复制

  • 在浅克隆中,对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有被复制




深克隆


对于引用类型单独克隆



  • Customer.java

/**
* @Description 客户
*/
public class Customer implements Cloneable {
// ... 省略,同上
/**
* 深克隆方式一 对于引用类型单独克隆
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Customer customer = (Customer) super.clone();
customer.address = (Address) customer.address.clone();
return customer;
}
}


  • Address.java

/**
* @Description 地址
*/
public class Address implements Cloneable {
// ... 省略,同上
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}


  • 输出如下:

Customer{name='张三', address=Address{province='四川省', city='成都市'}}
Customer{name='张三', address=Address{province='四川省', city='成都市'}}
false
--------------
Customer{name='张三', address=Address{province='浙江省', city='杭州市'}}
Customer{name='张三', address=Address{province='四川省', city='成都市'}}
false



序列化实现深克隆



  • Customer.java

import java.io.Serializable;
/**
* @Description 客户
*/
public class Customer implements Serializable {
// ... 省略,同上
/**
* 深克隆方式二 序列化
* @return
*/
public Customer deepClone() throws Exception {
// TODO 将对象写入流中
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ObjectOutputStream oss = new ObjectOutputStream(bao);
oss.writeObject(this);
// TODO 将对象从流中取出
ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (Customer) ois.readObject();
}
}


  • Address.java

import java.io.Serializable;
/**
* @Description 地址
*/
public class Address implements Serializable {
// 需要实现序列化的对象必须实现```Serializable```接口
// ... 省略,同上
}


  • 输出如下:

Customer{name='张三', address=Address{province='四川省', city='成都市'}}
Customer{name='张三', address=Address{province='四川省', city='成都市'}}
false
--------------
Customer{name='张三', address=Address{province='浙江省', city='杭州市'}}
Customer{name='张三', address=Address{province='四川省', city='成都市'}}
false


  • 在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将被复制




总结

  • 优点

1.原型模式是在内存中进行二进制流的拷贝,比直接new一个对象性能好


  • 缺点

1.必须配备克隆方法
2.对克隆复杂对象或对克隆出的对象进行复杂改造时容易引入风险
3.深拷贝、浅拷贝要运用得当


  • 适用场景

1.类初始化消耗较多资源
2.new产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
3.构造函数比较复杂
4.循环体中生产大量对象时


  • 原型模式源代码

Object、ArrayList、HashMap、CacheKey



源码

  • GitHub:https://github.com/Maggieq8324/design_pattern.git




- End -

- 个人学习笔记 -

- 仅供参考 -




推荐阅读
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • Ihavethefollowingonhtml我在html上有以下内容<html><head><scriptsrc..3003_Tes ... [详细]
  • 学习Java异常处理之throws之抛出并捕获异常(9)
    任务描述本关任务:在main方法之外创建任意一个方法接收给定的两个字符串,把第二个字符串的长度减1生成一个整数值,输出第一个字符串长度是 ... [详细]
  • Java程序设计第4周学习总结及注释应用的开发笔记
    本文由编程笔记#小编为大家整理,主要介绍了201521123087《Java程序设计》第4周学习总结相关的知识,包括注释的应用和使用类的注释与方法的注释进行注释的方法,并在Eclipse中查看。摘要内容大约为150字,提供了一定的参考价值。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 网址:https:vue.docschina.orgv2guideforms.html表单input绑定基础用法可以通过使用v-model指令,在 ... [详细]
author-avatar
xuxiao
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有