Java设计模式之创建型模式--原型模式
来源:互联网 发布:个人博客网站源码 编辑:程序博客网 时间:2024/05/10 11:54
一:简介
原型模式用起来很简单,我们只需实现Cloneable接口,重写clone方法即可。使用原型模式的目的,是为了避免初始化是需要消耗很多的资源,new一个对象时需要进行繁琐的数据准备。
二:例子
假设,创造一个人,设置他的性别,国籍,种类(黑人还是白人还是黄种人)。等等之类,比方说现在就这三个属性。
三:例子实现
1. 创建Type:
public class Type { //肤色 private String fuse; //头发颜色 private String toufa; public Type() { } public Type(String fuse, String toufa) { this.fuse = fuse; this.toufa = toufa; } public String getFuse() { return fuse; } public void setFuse(String fuse) { this.fuse = fuse; } public String getToufa() { return toufa; } public void setToufa(String toufa) { this.toufa = toufa; }}
Type类很简单。
2.创建People:
这个类需要被我去拷贝,所有需要实现Cloneable接口和重写clone方法
public class People implements Cloneable { //性别 private String sex; //国籍 private String nationality; //种类 private Type type; public People() { } public People(String sex, String nationality, Type type) { this.sex = sex; this.nationality = nationality; this.type = type; } //重写clone方法 @Override protected Object clone(){ People people = null; try { //拷贝一个人 people = (People) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return people; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getNationality() { return nationality; } public void setNationality(String nationality) { this.nationality = nationality; } public Type getType() { return type; } public void setType(Type type) { this.type = type; } @Override public String toString() { return "性别:"+sex+"\n国籍:"+nationality+"\n种类:\t肤色:"+type.getFuse()+"\t头发:"+type.getToufa(); }}
3.创建测试类:
public static void main(String[] args) { Type type = new Type("黄皮肤","黑头发"); People people = new People(); people.setSex("男"); people.setNationality("中国"); people.setType(type); System.out.println(people.toString()); //第一个人创建好了,那如果我们还要创建这样的一个人呢, //我们只需要clone一下就行了 People people1 = (People) people.clone(); System.out.println("---------------------"); System.out.println(people1.toString()); //修改一些属性 people1.setSex("女"); System.out.println("---------------------"); System.out.println(people1.toString()); } 结果: 性别:男 国籍:中国 种类: 肤色:黄皮肤 头发:黑头发 --------------------- 性别:男 国籍:中国 种类: 肤色:黄皮肤 头发:黑头发 --------------------- 性别:女 国籍:中国 种类: 肤色:黄皮肤 头发:黑头发
我们可以看到,我们拷贝了一个一模一样的人。当然我们也可以动态的修改复制出来的人的一些属性。这样我们的对象不再是new出来,不过clone和new都会在内存中分配地址。并不会减少内存的开销,只不过,我们有时候用new会有繁琐的操作,即使实际上只需改其中的一点点。所以我们用clone就会很好的避免这个问题。
对象拷贝时,构造方法并不会被执行
我们修改默认构造方法: public People() { System.out.println("构造方法被调用了!"); }其他代码都不变结果:构造方法被调用了!性别:男国籍:中国种类: 肤色:黄皮肤 头发:黑头发---------------------性别:男国籍:中国种类: 肤色:黄皮肤 头发:黑头发---------------------性别:女国籍:中国种类: 肤色:黄皮肤 头发:黑头发
我们可以看到,我们拷贝了两次,但是构造方法只是在最开始new的时候被调用了。
这是因为:
Object类的clone方法原理是从内存中(堆中)以二进制流的方法进行拷贝,重新分配一个内存块。
四:原型中的浅拷贝和深拷贝
1. 先看浅拷贝的例子
还是一个人,里面有个list
public class People implements Cloneable{ private ArrayList<String> array = new ArrayList<String>(); @Override protected People clone(){ People people = null; try { people = (People) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return people; } public List<String> getArray() { return array; } public void setValue(String value) { this.array.add(value); }}
直接测试
public static void main(String[] args) { People people = new People(); people.setValue("张三"); People p2 = people.clone(); p2.setValue("李四"); for (String s : people .getArray()) System.out.println(s); } 结果: 张三 李四
我们会发现,people里应该只有一个张三啊,怎么被拷贝一个对象后,那个拷贝对象添加了一个李四,为什么原先的对象中也被添加了,太奇怪了。
这里我们要明白两点:
1.我们的clone方法并不是Cloneable接口的而是Object这个父类的,你可以去点进去看,发现这个接口,并没有任何方法,这个接口只是作为一个标识,只有实现改接口的类才‘有可能’被拷贝,没错是有可能!那么如何让这可能变成肯定呢,那就是重写clone方法。
2.Object提供的clone方法,只能拷贝一些原始类型如int,long…也包括String。
2.深拷贝例子
我们只需修改People中clone的代码就可以了@Override protected People clone(){ People people = null; try { people = (People) super.clone(); //这句话,让我们的array在对象拷贝的时候也拷贝一下,这里注意我们不能用List,而是要用它的实现类ArrayList,因为接口并没有clone方法。 people.array = (ArrayList<String>)this.array.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return people; } 看看结果: 张三
我们发现这次被拷贝对象并没有和拷贝对象公用属性。而是各用个的。这就是深拷贝。
五:适用场景
参考设计模式
一是类初始化需要消化非常多的资源,这个资源包括数据、硬件资源
等;
二是通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式;
三是一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone的方法创建一个对象,然后由工厂方法提供给调用者。
- JAVA设计模式创建型模式之原型模式
- Java设计模式之创建型模式--原型模式
- 设计模式-创建型之原型模式
- java设计模式(创建型)之原型模式
- java设计模式——创建型之原型模式
- java 设计模式-创建模式之原型模式
- 设计模式之------创建型模式(五)-----原型模式
- (4)设计模式之原型模式(创建型模式)
- 【设计模式】创建型模式-原型模式
- 设计模式 - 创建型模式 - 原型模式
- 设计模式->创建型模式->原型模式
- (创建模式)设计模式之Prototype(原型)
- 【创建型模式】原型模式(Prototype)之23种java设计模式
- Java设计模式之创建型模式-原型模式(Prototype)
- java设计模式之原型设计模式
- 设计模式笔记--创建型模式之四--原型prototype
- 设计模式之Prototype(原型模式)对象创建型
- 设计模式(创建型)之原型模式(Prototype Pattern)
- 使用 ./a.out > log.txt 将log写入文件
- 心率检测仪的设计与实现
- v-model 数据双向绑定
- 一键生成Android/Android-HD/IOS 多尺寸ICON
- 核心Dom节点访问
- Java设计模式之创建型模式--原型模式
- static成员在JVM中的存储
- 动态规划实例(十三):最长公共子串(LCS)
- jumpgame
- 顺序图
- libigl安装
- 0CTF-EasiestPrintf真的很easy
- Spark SQL RDD与DataFrames相互转换
- IOS Storyboard页面切换详解