Java设计模式—原型模式(prototype pattern)

原型模式是一种创建型设计模式,通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。

原型模式要求对象实现一个可以“克隆”自身的接口,该接口通过复制一个实例对象本身来创建一个新的实例。那么其他货币资金原型实例创建新的对象时就无需关心这个实例本身的类型,只要实现克隆自身的方法,就可以通过这个方法来获取新的对象,没java编译器必要再去通过new来创建。

原型模式的两种表java怎么读现形式

原型模式有两种表现形式(仅仅是原型模式的不同实现):简单形式和登记形式。

简单形式的原型模java编译器

Java设计模式—原型模式(prototype pattern)

这种模式涉及到三种角色分别如下:

1)客户(Client)角色:客户类提出创建js原型对象对象其他综合收益的请求。

public class Client {
/**
* 原型接口对象
*/
private Prototype prototype;
/**
* 构造方法
*/
public Client(Prototype prototype){
this.prototype = prototype;
}
public void operation(Prototype example){
Prototype copyPrototype = prototype.clone();


}
}

2)抽象原型(Prototype)角色:这是一个抽象角色,通常javaee由一个Java接口或Java抽象类实现。此角色给出所有的具体原型类所需的接口。

public interface Prototype{
/**
* 克隆自身的方法
*/
public Object clone();
}

3)具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。

public class ConcretePrototype1 implements Prototype {
public Prototype clone(){
Prototype prototype = new ConcretePrototype1();
return prototype;
}
}
public class ConcretePrototype2 implements Prototype {
public Prototype clone(){
//最简单的克隆,新建一个自身对象,由于没有属性就不再复制值了
Prototype prototype = new ConcretePrototype2();
return prototype;
}
}

登记形式的原型模式

登记形式相比简单形式多了一个原型管理器(PrototypeManager)角色,该角色的作用是创建具体原型类的对象java怎么读,并记录每一个被创建的对象。

Java设计模式—原型模式(prototype pattern)

原型管理器角色保持一个聚集,作为对所有原型对象的登记,这个角色提供必要的方法,供外界增加新的原型对象和取得已经登记过的原型对象。

public class PrototypeManager {
/**
* 记录原型的编号和原型实例的对应关系
*/
private static Map<String,Prototype> map = new HashMap<String,Prototype>();
/**
* 私有化无参构造方法
*/
private PrototypeManager(){}
/**
* 原型管理器添加或是修改某个原型注册
* @param prototypeId 原型编号
* @param prototype 原型实例
*/
public synchronized static void setPrototype(String prototypeId , Prototype prototype){
map.put(prototypeId, prototype);
}
/**
* 从原型管理器中删除某个原型注册
* @param prototypeId 原型编号
*/
public synchronized static void removePrototype(String prototypeId){
map.remove(prototypeId);
}
/**
* 获取某个原型编号对应的原型实例
* @param prototypeId 原型编号
* @return 原型编号对应的原型实例
* @throws Exception 如果原型编号对应的实例不存在,则抛出异常
*/
public synchronized static Prototype getPrototype(String prototypeId) throws Exception{
Prototype prototype = map.get(prototypeId);
if(prototype == null){
throw new Exception("您希望获取的原型还没有注册或已被销毁");
}
return prototype;
}
}

两种形式的区别

当创建的原型对象数目较少而且比较固定的话,采java面试题取简单形式。在这种情况下,原型对象的引用可以由客户端自己保存。

当创建的原型对象数目不固其他综合收益属于什么科目定的其他应收款话,采取登记形java编译器式。在这种情况下,客户端不保存对原型对象的引用,这个任务被交给系统运维工程师管理员对象。在复原型对象制一个原型对象之前,客户端可以查看管理员对象是否已经有一个满足要求的原型其他业务收入对象。如果有,可以直接从管理员类取得这个对象引用;反之,客户端就需要自行复其他应收款制此原型对象。

浅拷贝与深拷贝

原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Prototype类需要具备以下两个条件:

1)实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上java怎么读使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出 CloneNotSupportedException异常。

2)重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Proto其他应付款type类需要将clone方法的作用域修改为public类型。

注:Object类的clone方java模拟器法只会拷贝java中的8中基本类型以及他们的封装类型,另外还有String类型。对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。

浅拷贝(shallow copy)

被复制对象的所有变量都含有与原来的javascript对象相同的值(仅对于简单的值类型数据),而其他应收款所有的对其他对象的引用都仍然指向原来的对象。换言其他综合收益之,只负责克隆按值传递的数据(比如:基本数据类型、String类型)。

实体类,具体代码如下:

package com.yoodb;


public class Prototype implements Cloneable{
private String name;


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


@Override
protected Object clone() {
// TODO Auto-generated method stub
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}




}

测试函数,具体代码如下:

package com.yoodb;


public class TestMain {
public static void main(String[] args) {
Prototype pro = new Prototype();
pro.setName("欢迎收藏www.yoodb.com");
Prototype prot = (Prototype) pro.clone();
prot.setName("欢迎收藏www.yoodb.com");
System.out.println("original object:" + pro.getName());
System.out.println("cloned object:" + prot.getName());
}


}

运行结果如下:

original object:欢迎收藏www.yoodb.com
cloned object:欢迎收藏www.yoodb.com

系统运维主要做什么拷贝 (deep copy)

被复制对象的所有的变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对其他垃圾象,而不再是原有的那些被引用的对象。换言之,除了浅度克隆要克隆的值外,还负责其他应收款是什么科目克隆引用类型的数据,基本上就是被克隆实例所有的属性的数据都会被克隆出来。

实例一

实体类,具体代java环境变量配置码如下:java编译器

package com.yoodb;


public class Prototype implements Cloneable{
private String name;


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


@Override
protected Object clone() {
// TODO Auto-generated method stub
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}




}
//实体二
package com.yoodb;


public class NewPrototype implements Cloneable{
private String id;


private Prototype prototype;


public String getId() {
return id;
}


public void setId(String id) {
this.id = id;
}


public Prototype getPrototype() {
return prototype;
}


public void setPrototype(Prototype prototype) {
this.prototype = prototype;
}


@Override
protected Object clone() {
NewPrototype prot = null;
try {
prot = (NewPrototype) super.clone();
prot.prototype = (Prototype) this.getPrototype().clone();
return prot;
} catch (Exception e) {
// TODO: handle exception
}
return null;
}




}

测试函数,具体代码如下:

package com.yoodb;


public class TestMain {
public static void main(String[] args) {
//普通赋值
Prototype pro = new Prototype();
pro.setName("欢迎收藏blog.yoodb.com");
NewPrototype newPro = new NewPrototype();
newPro.setId("yoodb");
newPro.setPrototype(pro);
//克隆赋值
NewPrototype proc = (NewPrototype) newPro.clone();
proc.setId("yoodb");
proc.getPrototype().setName("欢迎收藏blog.yoodb.com");


System.out.println("original object id:" + newPro.getId());
System.out.println("original object name:" + newPro.getPrototype().getName());


System.out.println("cloned object id:" + proc.getId());
System.out.println("cloned object name:" + proc.getPrototype().getName());
}


}

运行结果如下:

original object id:yoodb
original object name:欢迎收藏blog.yoodb.com
cloned object id:yoodb
cloned object name:欢迎收藏blog.yoodb.com

实例二

利用串行化来实现深克隆,把对象写道流里其他应收款的过程是串行化(Serilization)过程;把对象从流中读出来是并行化(Deserialization)过程。

实体类,具体代码如下:

package com.yoodb;


import java.io.Serializable;


public class Prototype implements Serializable{


private static final long serialVersionUID = 1L;


private String name;


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


}
//实体二
package com.yoodb;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;


public class NewPrototype implements Serializable{


private static final long serialVersionUID = 1L;


private String id;


private Prototype prototype;


public String getId() {
return id;
}


public void setId(String id) {
this.id = id;
}


public Prototype getPrototype() {
return prototype;
}


public void setPrototype(Prototype prototype) {
this.prototype = prototype;
}


protected Object deepClone(){
try {
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(this);


ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
return oi.readObject();
} catch (Exception e) {
// TODO: handle exception
}
return null;
}


}

测试函数,具体代码如下:

package com.yoodb;


public class TestMain {
public static void main(String[] args) {
//普通赋值
Prototype pro = new Prototype();
pro.setName("欢迎收藏www.yoodb.com");
NewPrototype newPro = new NewPrototype();
newPro.setId("yoodb");
newPro.setPrototype(pro);
//克隆赋值
NewPrototype proc = (NewPrototype) newPro.deepClone();
proc.setId("yoodb");
proc.getPrototype().setName("欢迎收藏www.yoodb.com");


System.out.println("original object id:" + newPro.getId());
System.out.println("original object name:" + newPro.getPrototype().getName());


System.out.println("cloned object id:" + proc.getId());
System.out.println("cloned object name:" + proc.getPrototype().getName());
}


}

运行结果如下:

original object id:yoodb
original object name:欢迎收藏www.yoodb.com
cloned object id:yoodb
cloned object name:欢迎收藏www.yoodb.com

克隆满足的条件其他垃圾

clone()方法将对象复制了一份并返还给调用者。所谓“复制”的含义与clone()方法是怎么实现的。其他和其它的区别一般而言,clone()方法满足以下的描述:

1)对任何的对象x,都有:x.clone()!=x。换言之,克隆对象与原对象不是同一个对象。

2)对系统运维是干嘛的任何的对象x,都有:x.clone()java培训.getClass() =其他垃圾有哪些东西= x.getClass(),换言之,克隆对象与原对象的类型一样。

3)如果对象x的equals()方法定义其恰当的话,那么x.clone().equals(x)应当成立的。

原型模式使用场景

1)资其他源优化场景。

2)类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。

3)性能和安全要求的场景。

4)通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。

5)一个对象多个修改者的场景。

6)一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。

7)在实际项目中,原型java环境变量配置模式很少单独出现,一般是和工厂方法模式一起出现,通过 clojava环境变量配置njava怎么读e 的方法创建一个对象,然后由工厂方法提供给调用者。

注:原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现Cloneable,重写,java模拟器深拷贝是通过实现 Serializable 读取二进制流。

原型模式优缺点

原型模式的优点是允许在运行期间,由客户来注册符合原型接口的实现类型,也可以动态地改系统运维工程师变具体的实现类型,看起来接口没有任何变化,然而运行的已经是另其他外一个类实例了其他和其它的区别。因为克隆一个原型就类似于实例化一个类。

原型模式的缺点是每一个类都java培训必须配备一个克隆方法。配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类来说不是很难,而对于已经有的类不一定很容易,特别是当一个类引用不支持序列化的间接对象,或者引用含有循环结构的时候。

Java设计模式—原型模式(prototype pattern)