java23种设计模式——四、原型模式
目录
java23种设计模式—— 一、设计模式介绍
java23种设计模式—— 二、单例模式
java23种设计模式——三、工厂模式
java23种设计模式——四、原型模式
java23种设计模式——四、原型模式
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
举个例子,就是当我们需要给电脑安装win10系统时需要去官网上下载win10系统的安装包。而安装包的大小都是很耗时的,还需要另一台电脑来操作。如果我们下载了一个安装包放在我们的u盘里,之后需要安装win10时是不是就省去了中间寻找,下载等时间呢
原型模式的克隆分为浅克隆和深克隆,Java 中的 Object 类提供了浅克隆的 clone() 方法,具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆,这里的 Cloneable 接口就是抽象原型类。其代码如下
浅克隆
新建一个实体类Sheep实现Cloneable 接口,重写clone()方法
/**
* @author codermy
* @createTime 2020/5/14
*/
public class Sheep implements Cloneable{
private String name;
private int age;
private String sex;
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Sheep(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
//克隆该实例,使用默认的clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
Sheep sheep =null;
sheep = (Sheep)super.clone();
return sheep;
}
}
测试
/**
* @author codermy
* @createTime 2020/5/14
*/
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Sheep sheep = new Sheep("tom",1,"male");
Sheep sheep1 = (Sheep)sheep.clone();
System.out.println(sheep.hashCode());
System.out.println(sheep);
System.out.println(sheep1.hashCode());
System.out.println(sheep1);
sheep1.setAge(2);
System.out.println(sheep1);
System.out.println(sheep);
}
}
输出
1163157884
Sheep{name='tom', age=1, sex='male'}
1956725890
Sheep{name='tom', age=1, sex='male'}
Sheep{name='tom', age=2, sex='male'}
Sheep{name='tom', age=1, sex='male'}
在浅克隆中,被复制对象的所有普通成员变量都具有与原来对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。也就是说,浅克隆仅仅复制所考虑的对象,不会复制它所引用的成员对象。
我们先新建一个Pearson类,作为对象属性
/**
* @author codermy
* @createTime 2020/7/24
*/
public class Person implements Cloneable{
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(){
}
public Person(String name){
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
我们先给Sheep实体类种添加一个对象属性
/**
* @author codermy
* @createTime 2020/6/16
*/
public class Sheep implements Cloneable {
private String name;
private int age;
private String sex;
public Person owner;//对象引用
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Person getOwner() {
return owner;
}
public void setOwner(Person owner) {
this.owner = owner;
}
public Sheep(String name, int age, String sex, Person owner) {
this.name = name;
this.age = age;
this.sex = sex;
this.owner = owner;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", owner=" + owner +
'}';
}
//克隆该实例,使用默认的clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
Sheep sheep =null;
sheep = (Sheep)super.clone();
return sheep;
}
}
测试类中测试
/**
* @author codermy
* @createTime 2020/6/16
*/
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Person owner = new Person("马云");
Sheep sheep = new Sheep("tom",1,"male", owner);//新建sheep类
Sheep sheep1 = (Sheep)sheep.clone();//克隆该类
System.out.println(sheep.hashCode() + " " + sheep.owner.hashCode());
System.out.println(sheep + " "+ sheep.owner);
System.out.println(sheep1.hashCode()+ " " + sheep1.owner.hashCode());
System.out.println(sheep1 + " " + sheep1.owner);
sheep1.owner.setName("马化腾");
System.out.println(sheep.owner);
System.out.println(sheep1.owner);
}
}
输出
1163157884 1956725890
Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'}
356573597 1956725890
Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'}
Person{name='马化腾'}
Person{name='马化腾'}
我们可以看出浅克隆时对象的引用仅仅是指向了原空间,而并没有复制对象。
深克隆
在深克隆中,对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制。
自定义clone过程实现深克隆
将上面Sheep类中的clone方法改写
@Override
protected Object clone() throws CloneNotSupportedException {
Sheep sheep =null;
sheep = (Sheep)super.clone();
sheep.owner = (Person) sheep.owner.clone();//引用对象的克隆方法
return sheep;
}
测试类测试
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Person owner = new Person("马云");
Sheep sheep = new Sheep("tom",1,"male", owner);
Sheep sheep1 = (Sheep)sheep.clone();
System.out.println(sheep.hashCode() + " " + sheep.owner.hashCode());
System.out.println(sheep + " "+ sheep.owner);
System.out.println(sheep1.hashCode()+ " " + sheep1.owner.hashCode());
System.out.println(sheep1 + " " + sheep1.owner);
sheep1.owner.setName("马化腾");
System.out.println(sheep.owner);
System.out.println(sheep1.owner);
}
}
输出
1163157884 1956725890
Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'}
356573597 1735600054
Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'}
Person{name='马云'}
Person{name='马化腾'}
这时候我们已经实现了深克隆,但是总觉得有点“浅浅克隆”的意思,如果person类中还有对象引用那不就是。。
禁止套娃
序列化实现深克隆
两个实体类实现序列化接口
Person类
public class Person implements Serializable {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
public Person(String name){
this.name = name;
}
}
Sheep类
/**
* @author codermy
* @createTime 2020/6/16
*/
public class Sheep implements Serializable {
private String name;
private int age;
private String sex;
public Person owner;//对象引用
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 String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Person getOwner() {
return owner;
}
public void setOwner(Person owner) {
this.owner = owner;
}
public Sheep() {
}
public Sheep(String name, int age, String sex, Person owner) {
this.name = name;
this.age = age;
this.sex = sex;
this.owner = owner;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", owner=" + owner +
'}';
}
}
实现
**
* @author codermy
* @createTime 2020/7/24
*/
public class Client {
public static void main(String[] args) throws Exception {
Person owner = new Person("马云");
Sheep sheep = new Sheep("tom",1,"male", owner);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(sheep);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
Sheep sheep1 =(Sheep) ois.readObject();
bos.flush();oos.flush();
bos.close();oos.close();
ois.close();
System.out.println("Sheep: " + sheep);
System.out.println("Sheep1: " + sheep1);
System.out.println("================================");
System.out.println("Sheep: " + sheep.hashCode() + "++++++++++" + sheep.owner.hashCode());
System.out.println("Sheep1: " + sheep1.hashCode() + "++++++++++" + sheep1.owner.hashCode());
System.out.println("================================");
sheep1.owner.setName("马化腾");
System.out.println("Sheep: " + sheep.owner);
System.out.println("Sheep1: " + sheep1.owner);
}
}
输出
1163157884 1956725890
Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'}
356573597 1735600054
Sheep{name='tom', age=1, sex='male', owner=Person{name='马云'}} Person{name='马云'}
Person{name='马云'}
Person{name='马化腾'}
原型模式的优缺点
优点:原型模式是在内存中二进制流的拷贝,要比new一个对象的性能要好,特别是需要产生大量对象时。
缺点:直接在内存中拷贝,构造函数是不会执行的。
java23种设计模式——四、原型模式的更多相关文章
- 二十四种设计模式:原型模式(Prototype Pattern)
原型模式(Prototype Pattern) 介绍用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象.示例有一个Message实体类,现在要克隆它. MessageModel usin ...
- c# 24种设计模式5原型模式(Prototype)
前言 原型模式其实C# Object中已经提供了一个Clone( )方法,平时很少用到,最近读Retrofit源码时候看到有这种使用方式. 定义 原型模式就是在系统clone()标记的基础上,对Clo ...
- java23种设计模式之四:建造者模式
在软件开发过程中有时需要创建一个复杂的对象,这个复杂对象通常由多个子部件按一定的步骤组合而成.例如:在新招收一个员工时,对个人信息对象的创建,在不同的阶段,需要个人信息的内容也不一样,姓名.性别.年龄 ...
- 【Unity与23种设计模式】原型模式(Prototype)
GoF中定义: "使用原型对象来产生指定类的对象,所以产生对象时,是使用复制原型对象来完成." Unity中 开发者可以组装游戏对象 它可以包括复杂的组件 组装好了之后,就可以将其 ...
- 23种设计模式之原型模式(Prototype)
在系统开发过程中,有时候有些对象需要被频繁创建,原型模式通过给出一个原型对象来指明所要创建的对象的类型,然后通过复制这个原型对象的办法,创建出更多同类型的对象.原型模式是一种对象创建型模式,用原型实例 ...
- 二十三种设计模式之原型模式的C#实现
原型模式就是通过拷贝快速创建一个新的对象 本例UML如图 ColorBase [Serializable] public abstract class ColorBase { public int R ...
- 23种设计模式之原型模式(Prototype Pattern)
原型模式 使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象 分析: 孙悟空:根据自己的形状复制(克隆)出多个身外身 软件开发:通过复制一个原型对象得到多个与原型对象一模一样的新对象 ...
- php设计模式四 ---- 原型模式
1.简介 用于创建重复的对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式 意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 主要解决:在运 ...
- Java--23种设计模式之decorator模式
装饰模式:装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性.动态给一个对象增加功能,这些功能可以再动态的撤消.增加由一些基本功能的排列组合而产生的非常大量的 ...
随机推荐
- Flutter中的绘图(Canvas&CustomPaint)API
本文是Flutter中Canvas和CustomPaint API的使用实例. 首先看一下我们要实现的效果: 结合动图演示,列出最终目标如下: 在程序运行后,显示一个小球: 每次程序启动后,小球的样式 ...
- Python os.open() 方法
概述 os.open() 方法用于打开一个文件,并且设置需要的打开选项,模式参数mode参数是可选的,默认为 0777.高佣联盟 www.cgewang.com 语法 open()方法语法格式如下: ...
- HTML 基础- 4个实例
HTML 基础- 4个实例 不要担心本章中您还没有学过的例子,高佣联盟 www.cgewang.com 您将在下面的章节中学到它们. HTML 标题 HTML 标题(Heading)是通过<h1 ...
- PHP count_chars() 函数
实例 返回一个字符串,包含所有在 "Hello World!" 中使用过的不同字符(模式 3): <?php高佣联盟 www.cgewang.com$str = " ...
- PHP simplexml_import_dom() 函数
实例 获取 DOM 文档节点并转换为 SimpleXML 节点: <?php$dom=new domDocument;高佣联盟 www.cgewang.com$dom->loadXML(& ...
- ajax模拟表单提交,后台使用npoi实现导入操作 方式二
页面代码: <form id="form1" enctype="multipart/form-data"> <div style=" ...
- 6.18 省选模拟赛 字符串 LCT SAM
LINK:字符串 看起来很难做 考虑一种暴力 建立SAM后每次查询暴力扫儿子. 期望得分10分.实际得分10分. 另外一种发现每次扫儿子过于暴力 可以每次儿子向上做贡献 每次都暴力向上跳. 期望得分1 ...
- C++文件操作和模板
1.数据层次 位 bit 字节 byte 域/记录 将所有记录顺序地写入一个文件---->顺序文件:一个有限字符构成的顺序字符流 C++标准库中:ifsteam,ofstream,fstream ...
- Windows系统护眼色设置
Win10&Win8系统设置护眼色1. windows+R键调出运行窗口(或者鼠标右击开始键,选择运行)2. 在运行窗口中输入 regedit 调出注册表编辑器3. 按照如下顺序找到windo ...
- ios 版本更新提示-硬更新/软更新
实现: 强制更新:每次弹框 非强制更新:一天提示一次 代码如下: 步骤一: 将检测更新写到APPDelegate的applicationDidBecomeActive中 步骤二: 检测是否需要更新 步 ...