GOF23设计模式之原型模式(prototype)
一、原型模式概述
1.通过new产生一个对象需要非常繁琐的数据准备和访问权限,则可以使用原型模式。
2.就是java中的克隆技术,以某个对象为原型,复制出新的对象,显然,新的对象具备原型对象的特点。
3.优势:效率高(直接克隆,避免了重新执行构造函数的过程)。
4.克隆类似于new,但是不同于new。
new创建出来的对象属性采用默认值,克隆出来的对象属性值完全和原型对象相同,并且克隆出的新对象不会影响原型对象,然后,再修改克隆对象的值。
是否使用原型模式比较:
1.如果需要创建大量不费时的对象,new的对象和clone的对象效率相当
2.如果需要创建大量耗时的对象,建议使用原型模式
二、原型模式三种实现方式
1.浅复制:类中实现 Cloneable接口,重写clone方法
2.深复制:类中实现 Cloneable接口,重写clone方法时将对象一起克隆
3.深复制:类中实现 Serializable接口,利用反序列化实现深克隆
三、使用浅复制实现原型模式
1.使用原型模式克隆多利羊
/**
* 原型模式(浅克隆)
* @author CL
*
*/
public class Sheep implements Cloneable {
private String name; public Object clone() throws CloneNotSupportedException {
return super.clone();
} public Sheep() {
} public Sheep(String name) {
this.name = name;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} }
2.测试
public class TestSheep {
public static void main(String[] args) throws Exception {
Sheep s1 = new Sheep("多利");
Sheep s2 = (Sheep) s1.clone(); //克隆对象
System.out.println(s1.hashCode()+"(原型对象)-->"+s1.getName());
System.out.println(s2.hashCode()+"(克隆对象)-->"+s2.getName());
s2.setName("少利"); //对克隆对象修改,不影响原对象的属性值
System.out.println("\n--------修改克隆对象的属性值后---------\n");
System.out.println(s1.hashCode()+"(原型对象)-->"+s1.getName());
System.out.println(s2.hashCode()+"(克隆对象)-->"+s2.getName());
}
}
控制台输出:
366712642(原型对象)-->多利
1829164700(克隆对象)-->多利 --------修改克隆对象的属性值后--------- 366712642(原型对象)-->多利
1829164700(克隆对象)-->少利
四、使用深复制实现原型模式(1)
1.使用原型模式克隆多利羊
import java.util.Date; /**
* 原型模式(深克隆)
* @author CL
*
*/
public class Sheep implements Cloneable {
private String name; private Birthday birthday; public Object clone() throws CloneNotSupportedException {
Sheep s = (Sheep) super.clone(); //克隆对象
s.birthday = (Birthday) this.birthday.clone();
return s;
} public Sheep() {
} public Sheep(String name, Birthday birthday) {
this.name = name;
this.birthday = birthday;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Birthday getBirthday() {
return birthday;
} public void setBirthday(Birthday birthday) {
this.birthday = birthday;
} } class Birthday implements Cloneable {
private Date birthday; protected Object clone() throws CloneNotSupportedException {
return super.clone();
} public Birthday() {
} public Birthday(Date birthday) {
this.birthday = birthday;
} public Date getBirthday() {
return birthday;
} public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
2.测试
import java.util.Date; /**
* 测试原型模式(深克隆)
* @author CL
*
*/
public class TestSheep { public static void main(String[] args) throws Exception {
Birthday date = new Birthday(new Date(5456464L));
Sheep s1 = new Sheep("多利", date);
Sheep s2 = (Sheep) s1.clone(); //克隆对象 System.out.println(s1.hashCode()+"(原型对象)-->"+s1.getName()+"-->"+s1.getBirthday().getBirthday());
System.out.println(s2.hashCode()+"(克隆对象)-->"+s2.getName()+"-->"+s2.getBirthday().getBirthday()); date.setBirthday(new Date()); //对原对象修改,克隆对象的属性值不改变 System.out.println("\n--------修改克隆对象的属性值后---------\n"); System.out.println(s1.hashCode()+"(原型对象)-->"+s1.getName()+"-->"+s1.getBirthday().getBirthday());
System.out.println(s2.hashCode()+"(克隆对象)-->"+s2.getName()+"-->"+s2.getBirthday().getBirthday());
} }
控制台输出:
366712642(原型对象)-->多利-->Thu Jan 01 09:30:56 CST 1970
1550089733(克隆对象)-->多利-->Thu Jan 01 09:30:56 CST 1970
366712642(原型对象)-->多利-->Fri Dec 29 17:03:26 CST 2017
1550089733(克隆对象)-->多利-->Thu Jan 01 09:30:56 CST 1970
五、使用深复制实现原型模式(2)
1.使用原型模式克隆多利羊
import java.io.Serializable;
import java.util.Date; /**
* 原型模式(利用反序列化实现深克隆)
* @author CL
*
*/
public class Sheep implements Serializable {
private String name; private Birthday birthday; public Sheep() {
} public Sheep(String name, Birthday birthday) {
this.name = name;
this.birthday = birthday;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Birthday getBirthday() {
return birthday;
} public void setBirthday(Birthday birthday) {
this.birthday = birthday;
} } class Birthday implements Serializable {
private Date birthday; public Birthday() {
} public Birthday(Date birthday) {
this.birthday = birthday;
} public Date getBirthday() {
return birthday;
} public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
2.测试
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date; /**
* 测试原型模式(利用反序列化实现深克隆)
* @author CL
*
*/
public class TestSheep { public static void main(String[] args) throws Exception {
Birthday date = new Birthday(new Date(5456464L));
Sheep s1 = new Sheep("多利", date); //利用反序列化实现深克隆
//1. 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(s1);
byte[] bytes = bos.toByteArray(); //2. 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
Sheep s2 = (Sheep) ois.readObject(); System.out.println(s1.hashCode()+"(原型对象)-->"+s1.getName()+"-->"+s1.getBirthday().getBirthday());
System.out.println(s2.hashCode()+"(克隆对象)-->"+s2.getName()+"-->"+s2.getBirthday().getBirthday()); date.setBirthday(new Date()); //对原对象修改,克隆对象的属性值不改变 System.out.println("\n--------------------修改克隆对象的属性值后---------------------\n"); System.out.println(s1.hashCode()+"(原型对象)-->"+s1.getName()+"-->"+s1.getBirthday().getBirthday());
System.out.println(s2.hashCode()+"(克隆对象)-->"+s2.getName()+"-->"+s2.getBirthday().getBirthday());
} }
控制台输出:
1442407170(原型对象)-->多利-->Thu Jan 01 09:30:56 CST 1970
1173230247(克隆对象)-->多利-->Thu Jan 01 09:30:56 CST 1970 --------------------修改克隆对象的属性值后--------------------- 1442407170(原型对象)-->多利-->Fri Dec 29 17:11:21 CST 2017
1173230247(克隆对象)-->多利-->Thu Jan 01 09:30:56 CST 1970
六、原型模式常见应用场景
1.原型模式很少单独出现,一般是和工厂方法模式一起出现。通过clone的方法创建一个对象,然后由工厂方法提供给调用者;
2.Spring中的bean的创建其实就是两种:单例模式和原型模式(+工厂模式);
3.………………
//对原型对象的修改
GOF23设计模式之原型模式(prototype)的更多相关文章
- GOF23设计模式之原型模式
GOF23设计模式之原型模式 1)通过 new 产生一个对象需要飞船繁琐的数据准备或访问权限,则可以使用原型模式. 2)就算 java 中的克隆技术,以某个对象为原型,复制出新的对象.显然,新的对象具 ...
- 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)
原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...
- 二十四种设计模式:原型模式(Prototype Pattern)
原型模式(Prototype Pattern) 介绍用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象.示例有一个Message实体类,现在要克隆它. MessageModel usin ...
- 【GOF23设计模式】原型模式
来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_原型模式.prototype.浅复制.深复制.Cloneable接口 浅复制 package com.test.prot ...
- [设计模式] 4 原型模式 prototype
设计模式:可复用面向对象软件的基础>(DP)本文介绍原型模式和模板方法模式的实现.首先介绍原型模式,然后引出模板方法模式. DP书上的定义为:用原型实例指定创建对象的种类,并且通过拷贝这些原型创 ...
- 设计模式 笔记 原型模式 prototype
//---------------------------15/04/07---------------------------- //prototype 原型模式--对象创建型模式 /* 1:意图: ...
- python 设计模式之原型模式 Prototype Pattern
#引入 例子1: 孙悟空拔下一嘬猴毛,轻轻一吹就会变出好多的孙悟空来. 例子2:寄个快递下面是一个邮寄快递的场景:“给我寄个快递.”顾客说.“寄往什么地方?寄给……?”你问.“和上次差不多一样,只是邮 ...
- 【UE4 设计模式】原型模式 Prototype Pattern
概述 描述 使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.如孙悟空猴毛分身.鸣人影之分身.剑光分化.无限剑制 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象, ...
- 【设计模式】—— 原型模式Prototype
前言:[模式总览]——————————by xingoo 模式意图 由于有些时候,需要在运行时指定对象时哪个类的实例,此时用工厂模式就有些力不从心了.通过原型模式就可以通过拷贝函数clone一个原有的 ...
随机推荐
- Oracle 使用小技巧
1.小数转换成字符往往会丢失前面的零. 解决方法: to_char(0.12345,'fm9999999990.00'); 2.除数为零的话oracle老是报错. 解决方法: decode(B,0,0 ...
- UML_02_概述
一.前言 UML(Unified Modeling Language)是一种统一建模语言,为面向对象开发系统的产品进行说明.可视化.和编制文档的一种标准语言 二.分类 UML 的核心是图表,大致可以将 ...
- PostgreSQL日志号LSN和wal日志文件简记
弄明白日志号的原理之后,一段时间又有点忘记了,干脆整理一遍: (一)wal文件命名规则 1)在$PGDATA目录下面的pg_xlog目录中存放着xlog日志文件(10.1之后变为了pg_wal): t ...
- Gradle2.0用户指南翻译——第三章. 教程
翻译项目请关注Github上的地址:https://github.com/msdx/gradledoc本文翻译所在分支:https://github.com/msdx/gradledoc/tree/2 ...
- mysql动态扩容调研
MySQL动态扩容方案 目前可用方案 MySQL的复制: 一个Master数据库,多个Salve,然后利用MySQL的异步复制能力实现读写分离,这个方案目前应用比较广泛,这种技术对于以读为主的应用很有 ...
- java入门学习(4)— 类,对象理解,如何创建类,对象
1.什么是类?具有一定相同的属性的对象的集合就叫类.2.对象:类的具体实例,就是类的实例化.比如学生是一个类(student),那学生里面的小红就是一个对象,一个有学生的属性的对象.3.如何定义一个类 ...
- 有关linux中,<math.h>的调用方法
h{font-weight:bold;color:green;font-size:105%} p{font-size:100%} linux下C语言程序中,若要用到math.h中的函数(如:sin() ...
- vuex(二)getters
getters: 有时候,我们需要对state的数据进行筛选,过滤.这些操作都是在组件的计算属性进行的.如果多个组件需要用到筛选后的数据,那我们就必须到处重复写该计算属性函数:或者将其提取到一个公共的 ...
- pymysql中的参数及方法
1.connect(参数) Connection = Connect(*args, **kwargs) Establish a connection to the MySQL database. Ac ...
- Android Hook框架Xposed详解
1 Introduction 1.1 概述 Xposed 是 GitHUB 上 rovo89 大大设计的一个针对 Android 平台的动态劫持项目,通过替换 /system/bin/app_pro ...