原型模式--java代码实现
原型模式
原型模式,属于对象创建型模式中的一种。通过复制原型对象的方法来创建一个对象实例,且该对象与原对象有相同的数据结构和值。类似我们在备份数据库信息的时候,将数据库中表的结构和数据的一同备份,生成一个数据库文件。
在Java环境中,要实现原型模式,要理解对象创建、引用和克隆的相关知识,在这里通过简单分析JVM的内存在对象创建、引用和克隆时栈和堆的内容变化,来深入理解原型模式是如何在Java环境中运作的。
1.简单理解JVM内存中栈和堆
栈:用来存放函数中定义的基本类型的变量和对象的引用变量。
堆:则是存放由new创建的对象和数组,对象内存储普通的变量和方法。对象创建后将其地址赋值给栈中的引用变量。
方法区:也是堆,这里面存放类代码、静态变量、静态方法和字符串常量等。
2.引用和克隆的区别
引用的示例图:

克隆的示意图:

由示例图我们可以看出,引用,比如person2=person1,栈中两个不同的成员变量指向对中的同一个对象,他们两个的值是一样的,都是该对象在内存中的地址。而克隆是将对象复制一份包括数据结构和值,将复制出的对象的地址赋值给栈中的另外一个成员变量person2。
3.浅层克隆和深层克隆
有没有注意到一个问题,如果普通变量是一个引用变量,比如数组,列表或map,那么克隆是否把引用变量(person1中的friends)所引用的对象也给复制一份呢。其实并没有,只是将引用变量的变量名和值复制了一份,他们还是用的同一个引用对象,这就是浅层克隆。如浅层克隆示意图所示。那么如果想要把引用变量所指的对象也复制一份,则需要重新新建一个对应的对象,将值传入对象中,返回给复制后的引用变量person2中的friends中。如深层克隆示意图所示。
浅层克隆示意图:

深层克隆示意图:

4.代码实现
Person类:
在Java中克隆该类需实现Cloneable接口,重写了Object的 clone() 方法,该方法会创建和返回一个Person类的一个复制,也就是上述所说的浅层复制。该类中添加了浅层克隆shallowClone()和深层克隆deepClone()。
package prototype; import java.util.ArrayList;
import java.util.List; public class Person implements Cloneable{
//姓名
private String name;
//年龄
private int age;
//朋友
private List<String> friends;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<String> getFriends() {
return friends;
}
public void setFriends(List<String> friends) {
this.friends = friends;
}
//重写toString方法
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", friends=" + friends + "]";
}
//浅层克隆
public Person shallowClone() {
try {
return (Person) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
//深层克隆
public Person deepClone() {
try {
Person person = (Person) super.clone();
List<String> newFriends = new ArrayList<String>();
for(String friend : this.getFriends()) {
newFriends.add(friend);
}
person.setFriends(newFriends);
return person;
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
MainClass:
通过向列表中添加值来测试浅层克隆和深层克隆。具体代码中有注释,请看代码。
package prototype; import java.util.ArrayList;
import java.util.List; public class MainClass {
public static void main(String[] args) {
//创建对象person1
Person person1 = new Person();
//初始化对象
person1.setName("zhangsan");
person1.setAge(20);
List<String> friends = new ArrayList<String>();
friends.add("lisi");
friends.add("wangwu");
person1.setFriends(friends);
//person2是浅层克隆
Person person2 = person1.shallowClone();
//person3是深层克隆
Person person3 = person1.deepClone();
//获取浅层克隆的friends的list对象
List<String> person2_friends = person2.getFriends();
//向引用对象中添加值
person2_friends.add("shallow");
person2.setFriends(person2_friends);
//获取深层克隆的friends的list对象
List<String> person3_friends = person3.getFriends();
//向引用对象中添加值
person3_friends.add("deep");
person3.setFriends(person3_friends); System.out.println("原型:"+person1);
System.out.println("浅层克隆:"+person2);
System.out.println("深层克隆:"+person3);
}
}
5.结果
从结果中可以发现,浅层克隆的person2中向friends列表中添加的shallow朋友,而在原型person1中也添加了shallow,验证了前面的说法。深层克隆person3是在person2之前克隆的,所以没有添加shallow朋友,而之后添加的deep朋友也没有影响person1和person2中的friends列表。
6.总结
通过结合JVM内存中的栈和堆来解释原型模型,利用Java代码成功测试。可以发现Java中默认是的克隆模式是浅层克隆,不复制引用变量所对应的对象。那么对于深层次的克隆,需要编写对应代码来复制。
原型模式--java代码实现的更多相关文章
- 设计模式之第9章-原型模式(Java实现)
设计模式之第9章-原型模式(Java实现) “快到春节了,终于快放假了,天天上班好累的说.”“确实啊,最近加班比较严重,项目快到交付了啊.”“话说一到过节,就收到铺天盖地的短信轰炸,你说发短信就发吧, ...
- 设计模式之原型模式——Java语言描述
原型模式是用于创建重复对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的方式 这种模式实现了一个原型接口,该接口用于创建当前对象的克隆.当直接创建对象的代价比较大时,则适 ...
- PrototypePattern(原型模式)-----Java/.Net
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式.
- 工厂方法模式--java代码实现
工厂方法模式 工厂方法模式,对简单工厂模式进行了升级.我们将水果园比作一个工厂,在简单工厂模式下,水果园是一个具体的工厂,直接用来生产各种各样的水果.那么在工厂方法模式下,水果园是一个抽象工厂,那么苹 ...
- 简单工厂模式--java代码实现
简单工厂模式 工厂,生产产品的场所.比如农夫山泉工厂,生产农夫山泉矿泉水.茶π等饮料.矿泉水和茶π都属于饮料,都具有解渴的功能,但是每种饮料给人的感觉是不一样的.矿泉水和茶π在Java中相当于子类,饮 ...
- 抽象工厂模式--java代码实现
抽象工厂模式 抽象工厂模式,对方法工厂模式进行抽象.世界各地都有自己的水果园,我们将这些水果园抽象为一个水果园接口,在中国.英国和美国都有水果园,种植不同的水果,比如苹果.香蕉和梨等.这里将苹果进行抽 ...
- 原型模式 —— Java的赋值、浅克隆和深度克隆的区别
赋值 直接 = ,克隆 clone 假如说你想复制一个简单变量.很简单: int a= 5; int b= a; b = 6; 这样 a == 5, b == 6 不仅仅是int类型,其它七种原始数 ...
- 深度分析:java设计模式中的原型模式,看完就没有说不懂的
前言 原型模式(Prototype模式)是指:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的 ...
- 重学 Java 设计模式:实战原型模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 老板你加钱我的代码能飞 程序员这份工作里有两种人:一类是热爱喜欢的.一类是仅当成工作 ...
随机推荐
- STL容器的基本特性和特征
1. STL有6种序列容器类型(1)vector它提供对元素的随即访问,在尾部添加和删除元素的时间是固定的,在头部或中部插入和删除元素的复杂度为线性时间.(2)deque在文件中声明.是双端队列,支持 ...
- .gitignore文件不起作用的解决方法
http://keendawn.blog.163.com/blog/static/88880743201531554431124/ git rm -r --cached . git add . git ...
- python3.6 安装win32api时候找不到regitry的问题
首先下载 https://sourceforge.net/projects/pywin32/files/pywin32/ 找到对应的即可 我需要的是这个 打开之后会提示3.6未注册 在任意位置新建一个 ...
- codeforces——961B. Lecture Sleep
本文为博主原创文章,未经允许不得转载. 我在csdn也同步发布了此文,链接 https://blog.csdn.net/umbrellalalalala/article/details/7989196 ...
- MariaDB/MySQL备份和恢复(一):mysqldump工具用法详述
本文目录:1.备份分类2.备份内容和备份工具3.mysqldump用法详述 3.1 语法选项 3.1.1 连接选项 3.1.2 筛选选项 3.1.3 DDL选项 3.1.4 字符集选项 3.1.5 复 ...
- mongodb的安装使用,window和centos环境
官网:https://www.mongodb.org/downloads 版本:最终稳定版 (mongodb-win32-x86_64-2008plus-ssl-3.2.6-signed.msi 绿色 ...
- 总结Array类型中常用的方法
Array类型应该是 ECMAScript 中最常用的类型之一了,并且它定义的数组与其他语言有着相当大的区别.数组是数据的有序集合,我们可以通过下标对指定位置的数据进行读 写:特别的是,在 ECMAS ...
- java面试总结
一.java的集合框架 HashMap.HashTable.CurrentHashMap的底层数据结构与区别? CurrentHashMap与HashTable是如何保证线程安全的? ArrayLis ...
- 管理和安装 chart - 每天5分钟玩转 Docker 容器技术(168)
安装 chart 当我们觉得准备就绪,就可以安装 chart,Helm 支持四种安装方法: 安装仓库中的 chart,例如:helm install stable/nginx 通过 tar 包安装,例 ...
- python装饰器小计
1.装饰器:本质是函数,是用来给其他函数添加附加扩展功能的函数,其返回值是一个函数(函数指针) 2.装饰器作用:不改变函数源代码和函数调用方式的前提下添加函数的附加功能. 3.装饰器储备知识点: A. ...
