- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Java设计模式之java原型模式详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
。
原型模式(Prototype Pattern):使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式是一种对象创建型模式.
原型模式的工作原理很简单:将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝自己来实现创建过程.
原型模式是一种“另类”的创建型模式,创建克隆对象的工厂就是原型类自身,工厂方法由克隆方法来实现.
需要注意的是通过克隆方法所创建的对象是全新的对象,它们在内存中拥有新的地址,通常对克隆所产生的对象进行修改对原型对象不会造成任何影响,每一个克隆对象都是相互独立的。通过不同的方式修改可以得到一系列相似但不完全相同的对象.
。
Prototype
(抽象原型类):它是声明克隆方法的接口,是所有具体原型类的公共父类,可以是抽象类也可以是接口,甚至还可以是具体实现类。ConcretePrototype
(具体原型类):它实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。Client
(客户类):让一个原型对象克隆自身从而创建一个新的对象,在客户类中只需要直接实例化或通过工厂方法等方式创建一个原型对象,再通过调用该对象的克隆方法即可得到多个相同的对象。由于客户类针对抽象原型类Prototype编程,因此用户可以根据需要选择具体原型类,系统具有较好的可扩展性,增加或更换具体原型类都很方便。原型模式的核心在于如何实现克隆方法.
。
学过Java语言的人都知道,所有的Java类都继承自 java.lang.Object。事实上,Object 类提供一个 clone() 方法,可以将一个Java对象复制一份。因此在Java中可以直接使用 Object 提供的 clone() 方法来实现对象的克隆,Java语言中的原型模式实现很简单.
需要注意的是能够实现克隆的Java类必须实现一个 标识接口 Cloneable,表示这个Java类支持被复制。如果一个类没有实现这个接口但是调用了clone()方法,Java编译器将抛出一个 CloneNotSupportedException 异常.
。
具体原型类
//实现Cloneable接口@Datapublic class Sheep implements Cloneable{ private String name; private Integer age; //重写Object的clone方法 @Override protected Object clone() throws CloneNotSupportedException { Sheep sheep=null; sheep=(Sheep)super.clone(); return sheep; }}
客户端创建并克隆原型对象:
//创建原型对象 Sheep sheep=new Sheep(); sheep.setAge(3); sheep.setName("肖恩"); //克隆 Sheep sheep1 = sheep.clone(); Sheep sheep2=sheep.clone(); System.out.println(sheep1); System.out.println(sheep2); System.out.println(sheep1==sheep2);
。
看一眼 Object#clone 方法 。
protected native Object clone() throws CloneNotSupportedException;
这是一个 native 关键字修饰的方法 。
一般而言,Java语言中的clone()方法满足:
在派生类中覆盖基类的 clone() 方法,并声明为public; 。
在派生类的 clone() 方法中,调用 super.clone(); 。
派生类需实现Cloneable接口.
此时,Object类相当于抽象原型类,所有实现了Cloneable接口的类相当于具体原型类.
。
pig类
@Data@AllArgsConstructor@NoArgsConstructorpublic class Pig { String name; Integer age;}
sheep类
//实现Cloneable接口@Datapublic class Sheep implements Cloneable{ private String name; private Integer age; private Pig pig; //重写Object的clone方法 @Override protected Sheep clone() throws CloneNotSupportedException { Sheep sheep=null; sheep=(Sheep)super.clone(); return sheep; }}
客户端进行克隆
public class test{ @Test public void test() throws CloneNotSupportedException { //创建原型对象 Sheep sheep=new Sheep(); sheep.setAge(3); sheep.setName("肖恩"); sheep.setPig(new Pig("大忽悠",3)); //克隆 Sheep sheep1 = sheep.clone(); Sheep sheep2=sheep.clone(); System.out.println(sheep1); System.out.println(sheep2); System.out.println(sheep1==sheep2); System.out.println("=============================="); System.out.println(sheep1.getPig()==sheep2.getPig()); }}
这里对Sheep类里面的引用类型Pig的克隆方式只是简单的地址拷贝,即浅拷贝操作 。
。
浅克隆:
深克隆:
。
Pig类首先需要实现克隆即可,并重写clone方法
@Data@AllArgsConstructor@NoArgsConstructorpublic class Pig implements Cloneable{ String name; Integer age; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}
sheep类
//实现Cloneable接口@Datapublic class Sheep implements Cloneable{ private String name; private Integer age; private Pig pig; //重写Object的clone方法 @Override protected Sheep clone() throws CloneNotSupportedException { Sheep sheep=null; sheep=(Sheep)super.clone(); sheep.pig=(Pig)sheep.pig.clone(); return sheep; }}
。
对象可以序列化的前提是实现了Serializable接口,这里Sheep和Pig都需要实现该接口 。
pig类
@Data@AllArgsConstructor@NoArgsConstructorpublic class Pig implements Serializable{ String name; Integer age;}
sheep类
//实现Cloneable接口@Datapublic class Sheep implements Serializable{ private String name; private Integer age; private Pig pig; //序列化方式完成深拷贝 public Sheep deepClone() throws IOException, ClassNotFoundException { //先将要序列化的对象写入流中 ByteArrayOutputStream baot=new ByteArrayOutputStream(); //ObjectOutputStream构造函数的参数是,将对象流写入到哪里 ObjectOutputStream oot=new ObjectOutputStream(baot); oot.writeObject(this); //将序列化的对象从流中读取出来 ByteArrayInputStream bait=new ByteArrayInputStream(baot.toByteArray()); ObjectInputStream oit=new ObjectInputStream(bait); return (Sheep) oit.readObject(); }}
。
饿汉式单例模式如下:
public class HungrySingleton implements Serializable, Cloneable { private final static HungrySingleton hungrySingleton; static { hungrySingleton = new HungrySingleton(); } private HungrySingleton() {} public static HungrySingleton getInstance() { return hungrySingleton; } private Object readResolve() { return hungrySingleton; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}
使用反射获取对象,测试如下 。
public class Test { public static void main(String[] args) throws CloneNotSupportedException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { HungrySingleton hungrySingleton = HungrySingleton.getInstance(); Method method = hungrySingleton.getClass().getDeclaredMethod("clone"); method.setAccessible(true); HungrySingleton cloneHungrySingleton = (HungrySingleton) method.invoke(hungrySingleton); System.out.println(hungrySingleton); System.out.println(cloneHungrySingleton); }}
输出 。
com.designpattern.HungrySingleton@34c45dca com.designpattern.HungrySingleton@52cc8049 。
可以看到,通过原型模式,我们把单例模式给破坏了,现在有两个对象了 。
为了防止单例模式被破坏,我们可以:不实现 Cloneable 接口;或者把 clone 方法改为如下 。
@Override protected Object clone() throws CloneNotSupportedException { return getInstance(); }
。
原型模式的主要优点如下:
原型模式的主要缺点如下:
。
。
在Spring中,用户也可以采用原型模式来创建新的Bean实例,从而实现每次获取的是通过克隆生成的新实例,对其进行修改时对原有实例对象不造成任何影响.
这里的原型模式,也就是常说的Spring中的多实例模式,Spring中还有大家熟知的单实例模式,即Sigleton 。
。
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我的更多内容! 。
原文链接:https://blog.csdn.net/m0_53157173/article/details/120015362 。
最后此篇关于Java设计模式之java原型模式详解的文章就讲到这里了,如果你想了解更多关于Java设计模式之java原型模式详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
好吧,我怀疑这是一个独特的情况,所以要么有人这样做了,要么有人认为这是不可能的,至少以我所要求的方式。 我有 2 个原型(prototype)变量(函数),一个是父变量,另一个是助手。我想做的是从助手
这是 JavaScript 大师的问题。我正在尝试更优雅地使用 JavaScript 原型(prototype)模型。这是我的实用程序代码(它提供了真实的原型(prototype)链并正确使用 ins
我们知道在 JavaScript 中有一个用于数组的 .forEach() 方法。但是字符串没有内置该方法。 那么,下面的代码片段有没有问题:String.prototype.forEach = Ar
我们知道在 JavaScript 中有一个用于数组的 .forEach() 方法。但是字符串没有内置该方法。 那么,下面的代码片段有没有问题:String.prototype.forEach = Ar
我看到了两种不同的模式和解释。来自 DailyJS 和许多其他人的一篇:矩形.prototype = new Shape(); 然后是 Crockford 的 here 这意味着只是 矩形.proto
尝试在 Object.prototype 以及 String.prototype 和 Number.prototype 上定义一个 hashCode 方法>。我正在使用以下方法定义原型(prototy
在本教程中,您将借助示例了解 JavaScript 中的原型。 在学习原型之前,请务必查看以下教程: JavaScript 对象 JavaScript 构造函数 如您所知,您可以使用对象构造函
当构造新对象时,该对象被设置为委托(delegate)任何尚未显式设置为其构造函数原型(prototype)的属性。这意味着我们可以稍后更改原型(prototype),并且仍然可以看到实例中的更改。
我正在努力获得更好的 JavaScript 实用知识。所以,我买了 Douglas Crockford 的书“JavaScript the good parts”。 我现在很难掌握原型(prototy
我的理解是相同类型的所有对象将共享相同的原型(prototype)。因此对原型(prototype)的更改将反射(reflect)在每个对象上。但是值类型的属性似乎不是这样。这种属性是如何存储的? f
这个问题在这里已经有了答案: 关闭 12 年前。 Possible Duplicate: JavaScript: Class.method vs. Class.prototype.method 创建
为什么在 MDN 函数中 polyfills 使用“if (!Array.prototype.filter)”? if (!Array.prototype.filter) { Array.prot
这个问题已经有答案了: Assigning prototype methods *inside* the constructor function - why not? (6 个回答) 已关闭 7 年
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 9 年前。 Improve this qu
面向对象有一个特征是继承,即重用某个已有类的代码,在其基础上建立新的类,而无需重新编写对应的属性和方法,继承之后拿来即用; 。 在其他的面向对象编程语言比如Java中,通常是指,子类继承父类的属性和
OOP 中原型(prototype)设计模式最重要的部分之一是我们不会从头开始创建新对象,我们只是使用 clone() 函数从现有对象克隆它们。 那么clone()函数是深拷贝还是浅拷贝? 如果它是一
在进行原型(prototype)设计时,您在多大程度上放弃了最佳实践来支持代码和修复黑客攻击?当然,代码并不打算在完整的生产环境中保留。 补充:我正在研究一个用 Python 制作的相当大的半工作原型
我开始学习设计模式。我知道原型(prototype)是用来制作我已经拥有的对象的精确副本,而享元是用来制作类似的对象。 我已经编写了 2D 平台游戏,例如马里奥(Java)。有很多相同的敌人,唯一的区
我正在使用 Maven 生成原型(prototype)。我能够使原型(prototype)生成正常,并且它生成的项目模板按预期工作。唯一的问题是在我的 shell 脚本中。脚本中注释掉的任何内容都会被
我想用 primefaces 配置一个 Java EE 项目。我在某处读到可以使用 mvn arechetype:generate 创建项目结构。当我使用它时,我只看到了 41 个选项,而在该教程中,
我是一名优秀的程序员,十分优秀!