首页 > 代码库 > 设计模式----原型模式
设计模式----原型模式
?
创建型模式
原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。就是依托一个已经实例化的对象去创建另外一个可以进行定制的对象,而不需要知道创建过程的具体细节。本质特点:在不重新初始化的情况下动态获取对象在运行时的状态。
在Java中直接实现接口Cloneable接口就可以了,override其中clone方法,
举个例子:在我们考证的时候,都要填写报名信息,每次都一样的,如果每次都要填写一样的信息会很烦,能不能写好一份后,以后不管什么考试都只要复制过去就好了呢?
报名信息类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | public class RestrationInfo implements Cloneable { private String name; private String birthday; private String school; private String ID; public RestrationInfo(String name){ this .name = name; } public void setBirthday(String birthday) { this .birthday = birthday; } public void setSchool(String school) { this .school = school; } public void setID(String iD) { ID = iD; } public void show(){ System.out.println( "name:" +name); System.out.println( " birthday:" + birthday); System.out.println( "school:" +school); System.out.println( "ID:" +ID); } @Override protected Object clone() throws CloneNotSupportedException { try { return super .clone(); } catch (CloneNotSupportedException e) { return null ; } } } |
客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class MyMain { public static void main(String[] args) { System.out.println( "cet 4" ); RestrationInfo restrationInfo = new RestrationInfo( "wang" ); restrationInfo.setBirthday( "XXXx" ); restrationInfo.setID( "dfd" ); restrationInfo.setSchool( "dfd" ); restrationInfo.show(); System.out.println( "cet 6" ); RestrationInfo restrationInfo2 = (RestrationInfo) restrationInfo.clone(); restrationInfo2.show(); } } |
这样就实现了一份信息,一直使用。如果我们只是简单的每次new一个对象的,就每次都要执行构造函数,如果构造函数复杂,就会影响到性能。在信息没有变化的情况下,复制是最好的解决方案。
问题:调用一个函数操作某对象的时候,常常会使得改对象陷入不可用的状态(不稳定状态),等操作结束后才会重新回到完全可用的状态。如果有线程企图访问一个处于不可用状态的对象,改对象会发生不能正确不相应的情况,由此会产生无法预料的后果。对一个实力对象进行克隆的时候,如果恰巧在多线程的情况下且该对象处于不稳定状态,那么克隆可能就会失败。所以说原型模式在实现时不是线程安全的。一定要在其属于稳定的情况下克隆。
问题:复制的深度,clone对于值类型的字段会逐位复制,而对于引用型的变量会复制引用但是不复制引用的对象,所以原始的对象和它的副本都引用同一个对象。这就是浅复制——被复制的对象的变量都与原来对象有相同的值,而所有的其他对象的引用都依然指向原来的对象。
也就是说如果我在报名信息里添加了地址信息,地址是一个单独的类,在复制报名信息的同时也要复制报名信息所引用的地址对象,使得报名信息对象的副本引用的是原国籍对象的副本。即让地址类也实现原型模式,实现Cloneable接口。
地质类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class Address implements Cloneable{ private String city; public String getCity() { return city; } public void setCity(String city) { this .city = city; } @Override protected Object clone() { try { return super .clone(); } catch (Exception e) { return null ; } } } |
修改后报名信息类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | protected Object clone() { // try { // return super.clone(); // } catch (CloneNotSupportedException e) { // return null; // } RestrationInfo objInfo = new RestrationInfo( this .address); objInfo.name = this .name; objInfo.ID = this .ID; objInfo.birthday= this .birthday; objInfo.school = this .school; return (Object)objInfo; } private Address address; public void setAddress(Address address){ this .address = address; } //just for clone private gouzao private RestrationInfo(Address address) { this .address = address; }
|
设计模式----原型模式