现在我们有这样一个需求。在后台输入一批学生的信息以后,封装成一个列表(List
),传送给前台打印出来。
这是第一版。
/**
* 这是最开始的Student 类
*/
public class Student1 {
private String name;
private int age;
private String teacher;
private String major;
// 各种setter 和getter
}
/**
* 第一个场景类:按照一开始的想法做的一个场景 ,现在我们是要把一批学生给记录到一个list里面,然后在页面打印出来
*/
public class Client1 {
public static void main(String[] args) {
List<Student1> list = new ArrayList<Student1>();// 建立存储学生信息的列表
Student1 student = new Student1();// 定义一个学生,接下来写好一样的信息
student.setAge(21);
student.setMajor("计算机");
student.setTeacher("黄大牛");
for (int i = 0; i < 10; i++) {
student.setName(RandomGenerator.getRandomLetters());
list.add(student);// 添加到列表中
}
System.out.println("将在页面上" + list.size() + "条记录,内容如下");
// 将列表返回给界面显示
for (Student1 _student : list) {
System.out.println("名字为 " + _student.getName() + " 的 "
+ _student.getMajor() + " 学院学生已经打印到界面");
}
}
}
结果如下:
将在页面上10条记录,内容如下
名字为 YdIkJf 的 计算机 学院学生已经打印到界面
名字为 YdIkJf 的 计算机 学院学生已经打印到界面
名字为 YdIkJf 的 计算机 学院学生已经打印到界面
名字为 YdIkJf 的 计算机 学院学生已经打印到界面
名字为 YdIkJf 的 计算机 学院学生已经打印到界面
名字为 YdIkJf 的 计算机 学院学生已经打印到界面
名字为 YdIkJf 的 计算机 学院学生已经打印到界面
名字为 YdIkJf 的 计算机 学院学生已经打印到界面
名字为 YdIkJf 的 计算机 学院学生已经打印到界面
名字为 YdIkJf 的 计算机 学院学生已经打印到界面
很明显,在list
里面用add()
方法是记下引用,而这个实际上的对象一直在变,所以所有的引用实际上都是指向同一个对象,结果当然是这样子。
得说题目要求就是返回一个列表,所以想在第一个循环里面打印的想法取消掉。那么只能这么改了。
for (int i = 0; i < 10; i++) {
Student1 student = new Student1();// 定义一个学生,接下来写好一样的信息
student.setAge(21);
student.setMajor("计算机");
student.setTeacher("黄大牛");
student.setName(RandomGenerator.getRandomLetters());
list.add(student);// 添加到列表中
}
的确能达到要求了,但是实际上造成了很多重复性动作,如果循环次数多,对象就成爆炸式增长。在这个情形下有了原型模式。事实上在开发中会经常有这样的情况,一个类需要做多次的数据库存储,但是每条记录又只是差那么一丁点,这时候就可以用原型模式了。
clone()
方法是基类Object
的一个方法,利用这个方法实现对象的复制。
修改后的代码如下:
/**
* 这是修改以后的Student类
*/
public class Student2 implements Cloneable {
private String name;
private int age;
private String teacher;
private String major;
public Student2 clone() {
Student2 student = null;
try {
student = (Student2) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return student;
}
//各种setter()和getter()
}
public static void main(String[] args) {
List<Student2> list = new ArrayList<Student2>();// 建立存储学生信息的列表
Student2 student = new Student2();// 定义一个学生,接下来写好一样的信息
student.setAge(21);
student.setMajor("计算机");
student.setTeacher("黄大牛");
for (int i = 0; i < 10; i++) {// 以下是各个学生不同的地方
Student2 _student = student.clone();
_student.setName(RandomGenerator.getRandomLetters());
list.add(_student);// 添加到列表中
}
System.out.println("将在页面上" + list.size() + "条记录,内容如下");
// 将列表返回给界面显示
for (Student2 _student : list) {
System.out.println("名字为 " + _student.getName() + " 的 "
+ _student.getMajor() + " 学院学生已经打印到界面");
}
}
这就是原型模式(Prototype
Pattern
)了。事实上这非常容易理解,也没什么难度,那么它有什么好处呢。貌似这也是对象的大量生成?
有什么好处?
1.
原型模式是在内存中做对象的复制,性能上比实例化一个对象要好很多;
2.
不希望初始化的时候要写构造方法的时候。
什么场景需要用到呢?
需要在频繁new
一个对象的时候,可以用到;一个对象需要提供给很多对象访问而且各个调用者都可能需要修改它的值的时候;……
浅拷贝和深拷贝的区别?
Java
在执行clone()
方法的时候,只是在内存中分配跟主对象一模一样的内存块,那有什么是包含在这个内存块里面的呢。有基本数据类型(String
很特殊的被包括了)和引用,还有不可变对象(final
)。但是引用的对象是不在的!这就出现了一个问题,对于被引用的东西,拷贝出来以后实际上被几个对象(包括原来的对象和拷贝出来的对象)共享着,这就不算真正意义上的拷贝了!因为实际生产中很多类不只是基本数据类型。这就是浅拷贝
。
那么我们应该怎么实现深拷贝
呢?其实很简单,在clone()
方法里面重新生成一个就是了。下面给出一段代码
:
浅拷贝
:跟我们之前的做法一样。
public class Student3 implements Cloneable {
private School school;
@Override
public Student3 clone() {
Student3 student = null;
try {
student = (Student3) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return student;
}
}
深拷贝
:在clone()
方法中也要重新克隆一个。
@Override
public Student3 clone() {
Student3 student = null;
try {
student = (Student3) super.clone();
student.school = (School) school.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return student;
}
事实上这个引用对象也必须实现clone()
方法。
分享到:
相关推荐
即原型模式,提供一个已经存在的对象进行新对象创建的接口,一般情况下都是使用Clone接口。 此模式非常简单,简单的说就是复制多个当前对象供使用。Prototype模式允许一个对象再创建另外一个可定制的对象,根本...
在软件设计中,原型模式是一种创建型设计模式,它提供了一种通过复制已有对象来创建新对象的方式,避免了重复的构造过程,提高了代码的效率和可维护性。原型模式的核心思想是利用对象的克隆功能来实现新对象的创建,...
JAVA-设计模式-创建型模式-原型模式
**原型模式(Prototype Pattern)**是一种创建型设计模式,它允许我们通过复制现有的对象来创建新对象,而不是通过构造函数或工厂方法。这种模式的核心在于,它提供了一种更高效、更灵活的方式来创建新实例,特别是在...
原型模式是创建型设计模式中的一种,用于创建重复的对象,同时又能保证性能。这种模式实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的成本过于高昂时,原型模式就显得尤为重要。 **原型模式的...
原型模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在原型模式中,一个对象可以在不暴露其构造函数的情况下被克隆,创建新对象的过程变得更加简单和高效。这种模式通常用于当需要大量创建相似对象时,...
在本实验中,我们将探讨五种常见的创建型设计模式:简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式,并在Java环境中实现这些模式。 1. **简单工厂模式**: - **概念**:简单工厂模式通过一个...
原型模式是一种创建型设计模式,它允许我们创建对象的克隆,而无需知道具体的实现细节。在软件工程中,当我们需要创建多个相似的对象时,使用原型模式可以大大提高效率,避免了每次都去创建新的对象。这种模式是基于...
原型模式是一种创建型设计模式,它的主要思想是通过复制已有对象来创建新对象,而不是通过构造函数来创建。这种模式适用于对象创建成本较高或者初始化过程复杂的情况,通过克隆已存在的对象,可以显著提升效率。 在...
本篇文章将深入探讨C#中的“原型模式”(Prototype Pattern),这是一种创建型设计模式,它允许我们通过复制已有对象来创建新对象,而不是从零开始创建。 原型模式的核心思想是克隆。在C#中,对象的克隆可以通过...
**原型模式(Prototype Pattern)**是软件设计模式中的结构型模式之一,主要用来简化实例化过程,减少类的创建。在原型模式中,一个对象可以被用作创建其他新对象的模板,通过复制已有对象来创建新对象,而不是通过new...
原型模式(Prototype Pattern)是一种创建型设计模式,它允许我们通过复制现有的对象来创建新对象,而无需知道具体创建过程的细节。这种模式的核心在于,它提供了一种对象克隆的简便方法,使得对象的创建过程对用户...
原型模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在原型模式中,一个对象可以被克隆以创建新对象,而无需知道具体的创建细节。这种模式在需要重复创建相似对象时非常有用,避免了每次创建新对象时都...
原型模式是其中一种经典的设计模式,它属于创建型模式,主要应用于对象复制或克隆场景。在这个实验六:“原型模式.rar”中,我们将深入理解并实践如何在Java中实现原型模式。 首先,原型模式的核心思想是通过拷贝已...
原型模式(Prototype Pattern)是软件设计模式中的一种结构型模式,它的主要目的是通过复制已有对象来创建新对象,从而减少创建新对象的成本。在原型模式中,类的实例化过程被替换为对已有实例的克隆操作,尤其适用...
原型模式是一种创建型设计模式,它的主要思想是通过复制已有对象来创建新对象,而不是通过构造函数来创建。这种模式可以有效地减少对象创建时的开销,尤其是在需要创建大量相似对象的情况下。在Android中,原型模式...
在本课程中,我们将深入探讨C#编程中的一个重要设计模式——Prototype原型模式,它是创建型设计模式的一种。原型模式主要用于简化实例化过程,通过复制已有对象来创建新对象,而不是直接通过构造函数来创建。这一...
原型模式是一种创建型设计模式,它的核心思想是通过复制已有对象来创建新对象,而不是通过构造函数来全新创建。这种模式在需要频繁创建和删除对象的场景中尤其有效,因为它可以显著减少内存分配和释放的操作,提升...