本文源码:GitHub·点这里 || GitEE·点这里

一、原型模式简介

1、基础概念

原型模式属于对象的创建模式。通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。

2、模式结构

原型模式要求对象实现一个可以“克隆”自身的接口,这样就可以通过复制一个实例对象本身来创建一个新的实例。这样一来,通过原型实例创建新的对象,就不再需要关心这个实例本身的类型,只要实现了克隆自身的方法,就可以通过这个方法来获取新的对象,而无须再去通过new来创建。

3、代码实现

1)、UML关系图



2)、核心角色

这种形式涉及到三个角色:

1)、客户(Client)角色:客户类提出创建对象的请求。

2)、抽象原型(Prototype)角色:这是一个抽象角色,通常由一个Java接口或Java抽象类实现。此角色给出所有的具体原型类所需的接口。

3)、具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。

3)、基于JDK源码实现

/**
* 基于JDK源码方式实现原型模式
*/
public class C01_Property {
public static void main(String[] args) {
Product product = new Product("机械键盘","白色",100.00) ;
Product product1 = (Product) product.clone();
Product product2 = (Product) product.clone();
System.out.println(product1);
System.out.println(product2);
System.out.println(product1==product2); // false
}
}
class Product implements Cloneable {
private String name ;
private String color ;
private Double price ;
public Product(String name, String color, Double price) {
this.name = name;
this.color = color;
this.price = price;
}
@Override
public String toString() {
return "Product{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
", price=" + price +
'}';
}
@Override
protected Object clone() {
Product product = null ;
try{
product = (Product)super.clone() ;
} catch (Exception e){
e.printStackTrace();
}
return product ;
}
// 省略GET和SET方法
}

二、Spring框架应用

1、配置文件

<!-- 多例Bean -->
<bean id="sheep01" class="com.model.design.spring.node05.property.Sheep" scope="prototype" />
<!-- 单例Bean 默认: scope="singleton" -->
<bean id="sheep02" class="com.model.design.spring.node05.property.Sheep"/>

2、测试代码块

@Test
public void test01 (){
ApplicationContext context01 = new ClassPathXmlApplicationContext(
"/spring/spring-property.xml");
// 原型模式
Sheep sheep1 = (Sheep)context01.getBean("sheep01") ;
Sheep sheep2 = (Sheep)context01.getBean("sheep01") ;
System.out.println(sheep1==sheep2); // false
// 单例模式
Sheep sheep3 = (Sheep)context01.getBean("sheep02") ;
Sheep sheep4 = (Sheep)context01.getBean("sheep02") ;
System.out.println(sheep3==sheep4); // true
}

3、核心源码

  • 所在类:org.springframework.beans.factory.support.AbstractBeanFactory
  • 所在方法:doGetBean

1)、执行流程

if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
return AbstractBeanFactory.this.createBean(beanName, mbd, args);
} catch (BeansException var2) {
AbstractBeanFactory.this.destroySingleton(beanName);
throw var2;
}
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
var11 = null;
Object prototypeInstance;
try {
this.beforePrototypeCreation(beanName);
prototypeInstance = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

2)、单例多例判断

所以默认就是单例模式,指定[scope="prototype"]就是原型模式。

public boolean isSingleton() {
return "singleton".equals(this.scope) || "".equals(this.scope);
}
public boolean isPrototype() {
return "prototype".equals(this.scope);
}

三、深浅拷贝

1、浅拷贝

  1. 数据类型是基本数据类型、String类型的成员变量,浅拷贝直接进行值传递,也就是将该属性值复制一份给新的对象。
  2. 数据类型是引用数据类型的成员变量,比如说成员变量是数组、类的对象等,浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。实际上两个对象的成员变量都指向同一个实例。修改其中一个对象属性会影响到另一个对象的属性。
  3. 浅拷贝是使用默认的 clone()方法来实现。

2、深拷贝

1)、概念描述

除了浅拷贝要拷贝的值外,还负责拷贝引用类型的数据。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象,这种对被引用到的对象的复制叫做间接复制。

2)、源代码实现

序列化实现深度克隆

对象写到流里的过程是序列化(Serialization)过程;而把对象从流中读出来的过程则叫反序列化(Deserialization)过程。应当指出的是,写到流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。

在Java语言里深度克隆一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的拷贝)写到一个流里(序列化),再从流里读回来(反序列化),便可以重建对象。

/**
* 深拷贝和浅拷贝对比案例
*/
public class C02_DeepClone {
public static void main(String[] args) throws Exception {
Dog dog = new Dog("Tom") ;
Dog dog1 = (Dog)dog.clone() ;
Dog dog2 = (Dog)dog.clone() ;
// dog1:1639622804;dog2:1639622804
System.out.println("dog1:"+dog1.cat.hashCode()+";dog2:"+dog2.cat.hashCode());
Dog dog3 = (Dog)dog.deepClone() ;
Dog dog4 = (Dog)dog.deepClone() ;
// dog3:1937348256;dog4:1641808846
System.out.println("dog3:"+dog3.cat.hashCode()+";dog4:"+dog4.cat.hashCode());
}
} class Cat implements Serializable {
public String name ;
public Cat (String name){
this.name = name ;
}
}
class Dog implements Cloneable,Serializable {
public String name ;
public Cat cat ;
public Dog (String name){
this.name = name ;
this.cat = new Cat("Kit") ;
}
@Override
protected Object clone() {
Dog dog = null ;
try{
dog = (Dog)super.clone() ;
} catch (Exception e){
e.printStackTrace();
}
return dog ;
}
public Object deepClone() throws IOException, ClassNotFoundException{
//将对象写到流里面:序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//从流里面读出对象:反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}

四、优缺点总结

1、优点总结

原型模式允许在运行时动态改变具体的实现类型。原型模式可以在运行期间,由客户来注册符合原型接口的实现类型,也可以动态地改变具体的实现类型,看起来接口没有任何变化,但其实运行的已经是另外一个类实例了。因为克隆一个原型就类似于实例化一个类。

2、缺点总结

原型模式最主要的缺点是每一个类都必须配备一个克隆方法。配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类来说不是很难,而对于已经有的类不一定很容易,特别是当一个类引用不支持序列化的间接对象,或者引用含有循环结构的时候。

五、源代码地址

GitHub·地址
https://github.com/cicadasmile/model-arithmetic-parent
GitEE·地址
https://gitee.com/cicadasmile/model-arithmetic-parent

Java描述设计模式(05):原型模式的更多相关文章

  1. GoLang设计模式05 - 原型模式

    原型模式也是一种创建型模式,它可以帮助我们优雅地创建对象的拷贝.在这种设计模式里面,将克隆某个对象的职责交给了要被克隆的这个对象.被克隆的对象需要提供一个clone()方法.通过这个方法可以返回该对象 ...

  2. JAVA 设计模式之原型模式

    目录 JAVA 设计模式之原型模式 简介 Java实现 1.浅拷贝 2.深拷贝 优缺点说明 1.优点 2.缺点 JAVA 设计模式之原型模式 简介 原型模式是六种创建型设计模式之一,主要应用于创建相同 ...

  3. java设计模式4——原型模式

    java设计模式4--原型模式 1.写在前面 本节内容与C++语言的复制构造函数.浅拷贝.深拷贝极为相似,因此建议学习者可以先了解C++的该部分的相关知识,或者学习完本节内容后,也去了解C++的相应内 ...

  4. 设计模式_11_原型模式(prototype)深拷贝、浅拷贝

    设计模式_11_原型模式(prototype) 浅拷贝: package designPatternOf23; /** * 定义:用原型实例,指定创建对象的种类,并通过拷贝这些原型创建新的对象 * P ...

  5. 设计模式之 原型模式详解(clone方法源码的简单剖析)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 原型模式算是JAVA中最简单 ...

  6. C# Json反序列化 C# 实现表单的自动化测试<通过程序控制一个网页> 验证码处理类:UnCodebase.cs + BauDuAi 读取验证码的值(并非好的解决方案) 大话设计模式:原型模式 C# 深浅复制 MemberwiseClone

    C# Json反序列化   Json反序列化有两种方式[本人],一种是生成实体的,方便处理大量数据,复杂度稍高,一种是用匿名类写,方便读取数据,较为简单. 使用了Newtonsoft.Json,可以自 ...

  7. GOF23设计模式之原型模式

    GOF23设计模式之原型模式 1)通过 new 产生一个对象需要飞船繁琐的数据准备或访问权限,则可以使用原型模式. 2)就算 java 中的克隆技术,以某个对象为原型,复制出新的对象.显然,新的对象具 ...

  8. C#设计模式(6)——原型模式(Prototype Pattern)

    一.引言 在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在 ...

  9. 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)

    原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...

随机推荐

  1. hdu 1667 The Rotation Game ( IDA* )

    题目大意: 给你一个“井”子状的board,对称的由24个方块组成,每个方块上有123三个数字中的一个.给你初始状态,共有八种变换方式,求字典序最小的最短的的变换路径使得,board中间的八个方块上数 ...

  2. Winform中实现向窗体中拖放照片并显示以及拖放文件夹显示树形结构(附代码下载)

    场景 向窗体中拖拽照片并显示效果 向窗体中拖拽文件夹并显示树形结构效果 注: 博客主页: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 ...

  3. 微信Pcweb登录简介

    微信第三方PCweb扫码登录 准备工作 (1) 网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统. 在进行微信OAuth2.在进行微信OAuth2.0授权登录接入之 ...

  4. ReadWriteLock场景应用解析

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  5. vue-其他

    vue-resource // 2.1 导入 vue-resource import VueResource from 'vue-resource' // 2.2 安装 vue-resource Vu ...

  6. 如何在阿里云服务器上搭建wordpress个人网站

    1.购买云服务器.域名.域名解析.配置linux系统上的web环境.FTP等参照下面的链接. https://www.cnblogs.com/smyhvae/p/4965163.html?tdsour ...

  7. Python—解析HTML页面(HTMLParser)

    HTMLParser类的定义及常用方法 类的定义 HTMLParser主要是用来解析HTML文件(包括HTML中无效的标记). 参数convert_charrefs表示是否将所有的字符引用自动转化为U ...

  8. 二分查找(Java)

    题目: 编写程序,完成以下功能: (1)输入5个整数到数组中; (2)使用冒泡法对5个数按从小到大排序,输出排序后的数组; (3)输入一个整数X,在数组中用二分法查找X,找到输出X在数组中的下标,找不 ...

  9. Nuxt+Vuex初体验

    小呀嘛小二郎,背着书包上学堂... 今天一个困扰了我一周时间的问题终于被我解决了,值得庆祝 在Nuxt中使用Vuex实现数据存储 首先: 在store目录下新建一个index.js文件 需要有两个组件 ...

  10. MySQL 两张表关联更新(用一个表的数据更新另一个表的数据)

    有两张表,info1, info2 . info1: info2: 现在,要用info2中的数据更新info1中对应的学生信息,sql语句如下: UPDATE info1 t1 JOIN info2 ...