设计模式4---原型模式(Prototype Pattern)
原型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
通俗来说:原型模式就是深拷贝和浅拷贝的实现。
浅拷贝
只实现了值拷贝,对于引用对象还是指向原来的对象。
- 父类实现clone方法,子类没有实现clone方法,其效果是浅拷贝。
- 父类实现clone方法,子类也实现clone方法,本来我想应该是深拷贝了,没想到也是浅拷贝。
package com.prototype;
import java.io.Serializable;
public class Work implements Serializable,Cloneable{
private static final long serialVersionUID = 207835812839542204L;
private String job;
private double salary;
public Work(String job,double salary) {
this.job = job;
this.salary = salary;
}
@Override
public String toString() {
return "Work [job=" + job + ", salary=" + salary + "]";
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
package com.prototype;
import java.io.Serializable;
public class User implements Serializable,Cloneable{
private static final long serialVersionUID = -2260332138558500447L;
private String name = "";
private Work work = null;
public User(String name,String job,double salary) {
this.name=name;
work = new Work(job, salary);
}
public void changeJob(String job){
this.work.setJob(job);
}
/*只需要实现Cloneable接口,覆写clone方法,此处clone方法可以改成任意的名称,
因为Cloneable接口是个空接口,你可以任意定义实现类的方法名,如cloneA或者cloneB。
重点是super.clone()这句话,super.clone()调用的是Object的clone()方法,而在Object类中,clone()是native的。
*/
//浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "User [name=" + name + ", work=" + work + "]";
}
}
package com.prototype;
public class Main {
public static void main(String[] args) {
try {
User user1 = new User("zhangsan","ceo",100000);
User user2 = (User) user1.clone();
System.out.println(user1);
System.out.println(user2);
System.out.println("修改job");
user2.changeJob("cfo");
System.out.println(user1);
System.out.println(user2);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
//结果
User [name=zhangsan, work=Work [job=ceo, salary=100000.0]]
User [name=zhangsan, work=Work [job=ceo, salary=100000.0]]
修改job
User [name=zhangsan, work=Work [job=cfo, salary=100000.0]]
User [name=zhangsan, work=Work [job=cfo, salary=100000.0]]
深拷贝
即实现了值拷贝,也实现了对引用对象的拷贝。
- 法一
//深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。
//实现深复制,需要采用流的形式读入当前对象的二进制输入,再写出二进制数据对应的对象。
public Object deepClone() throws IOException, ClassNotFoundException{
//写入当前对象的二进制流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//读入二进制流产生的新对象
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
- 法二
//将User的拷贝方法修改为下面的方法。
@Override
protected Object clone() throws CloneNotSupportedException {
Work w = (Work) work.clone();//对其引用变量进行拷贝
User u = (User)super.clone();//自身拷贝
u.work = w;//引用变量重新赋值。
return u;
}
定义
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
使用场景
原型模式被用在频繁调用且极其相似的对象上,它会克隆对象并设置改变后的属性,而且消耗的资源较少。
代码举例实现
ProtoTypeImpl.java
package com.design.prototype;
public class ProtoTypeImpl implements Cloneable{
private int shallowClone;
private DeepClone deepClone = new DeepClone();
public ProtoTypeImpl() {
System.out.println("construct is called");
}
public void print() {
// TODO Auto-generated method stub
System.out.println(shallowClone);
System.out.println(deepClone.getS());
}
@Override
protected ProtoTypeImpl clone(){
// TODO Auto-generated method stub
try{
ProtoTypeImpl protoTypeImp = (ProtoTypeImpl) super.clone();
//protoTypeImp.shallowClone = this.shallowClone;
//protoTypeImp.deepClone = this.deepClone.clone();
return protoTypeImp;
}catch(Exception e){
e.printStackTrace();
return null;
}
}
public void setShallowClone(int shallowClone) {
this.shallowClone = shallowClone;
}
public void setS(String s){
deepClone.setS(s);
}
}
DeepClone.java
package com.design.prototype;
public class DeepClone implements Cloneable{
private String s;
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
@Override
protected DeepClone clone(){
// TODO Auto-generated method stub
try {
return (DeepClone)super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
App.java
package com.design.prototype;
public class App {
public static void main(String[] args) {
// TODO Auto-generated method stub
ProtoTypeImpl protoTypeImp = new ProtoTypeImpl();
protoTypeImp.setShallowClone(1);
protoTypeImp.setS("deep clone");
protoTypeImp.print();
System.out.println("-------------");
ProtoTypeImpl protoTypeImp2 = protoTypeImp.clone();
protoTypeImp2.setShallowClone(2);
protoTypeImp2.setS("deep clone 2");
protoTypeImp2.print();
System.out.println("-------------");
protoTypeImp.print();
}
}
结果分析
这个现象主要是由于深浅复制引起的,普通类型的数据没有问题,而对象类型则有问题。同时我们应该注意到clone的时候构造函数是不会被调用的。
去掉ProtoTypeImpl.clone的两行注释(第一行没什么所谓,但是还是加上,有个对比)
运行结果2.png总结优缺点
- 优点
原型模式是在内存二进制流的拷贝,要比直接 new 一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其点。 - 缺点
使用过程中要切记构造函数不会被调用,所以在构造函数完成的操作应该多加处理,还有深浅复制的问题
- 优点
设计模式4---原型模式(Prototype Pattern)的更多相关文章
- 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)
原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...
- 二十四种设计模式:原型模式(Prototype Pattern)
原型模式(Prototype Pattern) 介绍用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象.示例有一个Message实体类,现在要克隆它. MessageModel usin ...
- python 设计模式之原型模式 Prototype Pattern
#引入 例子1: 孙悟空拔下一嘬猴毛,轻轻一吹就会变出好多的孙悟空来. 例子2:寄个快递下面是一个邮寄快递的场景:“给我寄个快递.”顾客说.“寄往什么地方?寄给……?”你问.“和上次差不多一样,只是邮 ...
- 【UE4 设计模式】原型模式 Prototype Pattern
概述 描述 使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.如孙悟空猴毛分身.鸣人影之分身.剑光分化.无限剑制 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象, ...
- Net设计模式实例之原型模式( Prototype Pattern)
一.原型模式简介(Brief Introduction) 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. Specify the kin ...
- 设计模式系列之原型模式(Prototype Pattern)——对象的克隆
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- 【设计模式】原型模式 Pototype Pattern
前面讲了创建一个对象实例的方法单例模式Singleton Pattern, 创造多个产品的工厂模式(简单工厂模式 Simple Factory Pattern, 工厂方法模式 FactoryMothe ...
- php原型模式(prototype pattern)
练练练,计划上午练完创建型设计模式. <?php /* The prototype pattern replicates other objects by use of cloning. Wha ...
- 2.6 《硬啃设计模式》第8章 复制不是很难 - 原型模式(Prototype Pattern)
案例: 某即时战略游戏,你训练出来各种很强的战士. 为了增加游戏的可玩性,增加了一种复制魔法.实施该魔法,可以复制任意的战士. 你会怎样考虑这个设计? 在继续阅读之前,请先认真思考并写出你的设计,这样 ...
- C#设计模式——原型模式(Prototype Pattern)
一.概述 在软件开发中,经常会碰上某些对象,其创建的过程比较复杂,而且随着需求的变化,其创建过程也会发生剧烈的变化,但他们的接口却能比较稳定.对这类对象的创建,我们应该遵循依赖倒置原则,即抽象不应该依 ...
随机推荐
- Python的urllib和urllib2模块
Python的urllib和urllib2模块都做与请求URL相关的操作,但他们提供不同的功能.他们两个最显着的差异如下: urllib2可以接受一个Request对象,并以此可以来设置一个URL的h ...
- 深入浅出 Java Concurrency (11): 锁机制 part 6 CyclicBarrier
如果说CountDownLatch是一次性的,那么CyclicBarrier正好可以循环使用.它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).所谓屏障 ...
- python开发_python中的函数定义
下面是我做的几个用列: #python中的函数定义,使用和传参 def_str = '''\ python中的函数以如下形式声明: def 函数名称([参数1,参数2,参数3......]): 执行语 ...
- css伪类(Pseudo-classes)
简介:伪类(Pseudo classes)是选择符的螺栓,用来指定一个或者与其相关的选择符的状态.它们的形式是selector:pseudo class { property: value; },简单 ...
- DBCA Does Not Display ASM Disk Groups In 11.2
DBCA Does Not Display ASM Disk Groups In 11.2 https://oraclehowto.wordpress.com/2011/08/15/dbca-does ...
- 使用Spring的HttpInvoker
Spring开发团队意识到RMI服务和基于HTTP的服务(例如Hessian和Burlap)之间的空白.一方面,RMI使用Java标准的对象序列化机制,但是很难穿透防火墙.另一方面,Hessian和B ...
- **__new__和__init__
这个__new__之前在写单例模式的时候用到过,下面做个深入了解吧. __new__是一个静态方法,而__init__是一个实例方法. __new__方法会返回一个创建的实例,而__init__什么都 ...
- Linux安装MariaDB+初始化数据库
背景说明: 在数据库中,mysql的是常用的数据库之一:作为一款开源的软件被广大公司所使用. 但是,mysql在被Oracle公司收购后,难免在以后会有取消开源的问题.所以急需一款新的数据库产品替换m ...
- 领域Command
一.项目结构 二.代码 /// <summary> /// /// </summary> public interface ICommand { } /// <summa ...
- iOS学习之自定义弹出UIPickerView或UIDatePicker(动画效果)
前面iOS学习之UIPickerView控件的简单使用 用到的UIPickerView弹出来是通过 textField.inputView = selectPicker; textField.in ...