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模式
装饰模式:装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性.动态给一个对象增加功能,这些功能可以再动态的撤消.增加由一些基本功能的排列组合而产生的非常大量的 ...
随机推荐
- ajax模拟表单提交,后台使用npoi实现导入操作 方式二
页面代码: <form id="form1" enctype="multipart/form-data"> <div style=" ...
- JavaScript正则表达式相关方法
一.正则表达式方法 var str="abcdefabcdef"; (1)reg.test(str); 查看字符串是否有满足正则表达式的内容,并返回一个布尔值true/false ...
- MySql大表分页(附独门秘技)
问题背景 MySql(InnoDB)中的订单表需要按时间顺序分页查询,且主键不是时间维度递增,订单表在百万以上规模,此时如何高效地实现该需求? 注:本文并非主要讲解如何建立索引,以下的分析均建立在有合 ...
- Mybatis insert 获取主键自增id
Mybatis insert 返回自增主键 mysql 准备一张带有自增主键的表users 字段:id,name,phone sql <!--插入记录并获取刚插入记录的主键--> < ...
- cocos2d-x_下载游戏引擎并创建第一个项目
我是一名小白. 下载并创建游戏项目 第一步:去官网下载cocos2d-x http://www.cocos.com/download 第二步:将安装包里边的 setup.py 拖进命令行点击回车键 , ...
- 铁大树洞与市面上现有APP对比
写在前面 铁大树洞这款APP严格来说并没有可以参照的对象,但如果非要说的话也可以有.这里我们选取百度贴吧进行对比. 百度贴吧 可以看到,百度贴吧的贴吧首页排版要更加好看,且在首页添加了各种分类.也许我 ...
- 用 Python 写个坦克大战
坦克大战是一款策略类的平面射击游戏,于 1985 年由 Namco 游戏公司发布,尽管时至今日已经有了很多衍生类的游戏,但这款游戏仍然受到了相当一部分人的欢迎,本文我们看一下如何使用 Python 来 ...
- mogilefs 安装与配置
安装步骤 配置yum 的epel源 yum install perl-Sys-Syslog perl-IO-AIO perl-Net-Netmask -y # 安装依赖的包 取得mogilefs的rp ...
- Java环境变量,jdk和jre的区别,面向对象语言编程
什么是java? java是一门面向对象的编程语言,包括java SE, java ME, Java EE . 广泛使用的是作为后端语言的Java EE开发, 面向对象和面向过程? java,C++ ...
- 微信公众号如何将PDF上传到公众号?
微信公众号如何将PDF上? 我们都知道创建一个微信公众号,在公众号中发布一些文章是非常简单的,但公众号添加附件下载的功能却被限制,如今可以使用小程序“微附件”进行在公众号中添加附件. 以下是公众号添加 ...