一、什么是原型模式
原型模式(Prototype)模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用 原型模式(Prototype)模式创建的实例,具有与原型一样的数据。
二、原型模式的特点
1,由原型对象自身创建目标对象。也就是说,对象创建这一动作发自原型对象本身。
2,目标对象是原型对象的一个克隆。也就是说,通过Prototype模式创建的对象,不仅仅与原型对象具有相同的结构,还与原型对象具有相同的值。
3,根据对象克隆深度层次的不同,有浅度克隆与深度克隆。
三、例子
创建一个原型类:
一个原型类,只需要实现Cloneable接口,覆写clone方法,此处clone方法可以改成任意的名称,因为Cloneable接口是个空接口。
public class Persion implements Cloneable{ // 姓名 private String name; // 年龄 private int age; // 性别 private String sex; //地址 private List<String> addr; public List<String> getAddr() { return addr; } public void setAddr(List<String> addr) { this.addr = addr; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } //浅复制 public Persion clone() { try { return (Persion) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } }
创建一个测试类:
public class TestClass { public static void main(String[] args) { Persion p1 = new Persion(); List<String> list = new ArrayList<String>(); list.add("测试地址"); p1.setAge(11); p1.setName("张三"); p1.setSex("男"); p1.setAddr(list); System.out.println("P1:age:" + p1.getAge() + " name:" + p1.getName() + " sex:" + p1.getSex() + " addr:" + p1.getAddr().toString()); //复制一个Persion对象 Persion p2 = p1.clone(); System.out.println("P2:age:" + p2.getAge() + " name:" + p2.getName() + " sex:" + p2.getSex() + " addr:" + p1.getAddr().toString()); //修改后的P2 p2.setAge(15); p2.setName("未完"); p2.setSex("女"); //向p1再次添加了一个地址,这会影响到p2的addr,可以看出浅复制对于引用类型复制的是引用类型的地址 list.add("测试地址2"); p1.setAddr(list); //修改p2并不会影响到p1, System.out.println("修改后的P1:age:" + p1.getAge() + " name:" + p1.getName() + " sex:" + p1.getSex() + " addr:" + p1.getAddr().toString()); System.out.println("修改后的P2:age:" + p2.getAge() + " name:" + p2.getName() + " sex:" + p2.getSex() + " addr:" + p2.getAddr().toString()); } }
浅复制和深复制:
浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。
可以看出浅复制对于引用类型只是复制了内存地址,并不是把引用类型再复制一份。我们可以深复制可以吧把引用类型也复制一份。
修改persion的clone方法如下:
//深复制 public Persion clone() { try { Persion p2 = (Persion) super.clone(); List<String> newAddrs = new ArrayList<String>(); for (String string : addr) { newAddrs.add(string); } p2.setAddr(newAddrs); return p2; } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } }
同样的测试代码再次运行:这次并没有影响到p2
三、原型模式应用场景
1,在创建对象的时候,我们不只是希望被创建的对象继承其基类的基本结构,还希望继承原型对象的数据。
2,希望对目标对象的修改不影响既有的原型对象(深度克隆的时候可以完全互不影响)。
3,隐藏克隆操作的细节。很多时候,对对象本身的克隆需要涉及到类本身的数据细节。