1.定义
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
说白了就是创建一个结构复杂的对象的创建工作与之前创建的对象几乎相同,只是个别变量不同的对象。
2.适用的场景
它主要面对的问题是:“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是他们却拥有比较稳定一致的接口。
3.UML图
4.实例
- 4.1写法1
public class Person implements Cloneable{
private String name;
private String age;
private String weight;
private String height;
private ArrayList<String> hobbies = new ArrayList<String>();
public Person(){
}
//深复制 浅复制
@SuppressWarnings("unchecked")
@Override
protected Object clone() throws CloneNotSupportedException {
// Person person =(Person) super.clone();
// return person;//浅复制 只能复制值 引用的地址未改变
Person person = (Person) super.clone();
person.hobbies = (ArrayList<String>) this.hobbies.clone();//深复制
return person;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
public ArrayList<String> getHobbies() {
return hobbies;
}
public void setHobbies(ArrayList<String> hobbies) {
this.hobbies = hobbies;
}
@Override
public String toString() {
return "{\"name\":\"" + name + "\",\"age\":\"" + age
+ "\",\"weight\":\"" + weight + "\",\"height\":\"" + height
+ "\",\"hobbies\":\"" + hobbies + "\"}";
}
}
- 4.2写法2
public class Person2 implements Cloneable{
private String name;
private String age;
private String weight;
private String height;
private ArrayList<String> hobbies = new ArrayList<String>();
public Person2(){
}
public Person2(Person2 person){
this.name = person.name;
this.age = person.age;
this.height = person.height;
this.weight = person.weight;
if (person.hobbies != null) {
this.hobbies = new ArrayList<String>(person.hobbies);
}
}
@Override
protected Object clone() throws CloneNotSupportedException {
return new Person2(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
public ArrayList<String> getHobbies() {
return hobbies;
}
public void setHobbies(ArrayList<String> hobbies) {
this.hobbies = hobbies;
}
@Override
public String toString() {
return "{\"name\":\"" + name + "\",\"age\":\"" + age
+ "\",\"weight\":\"" + weight + "\",\"height\":\"" + height
+ "\",\"hobbies\":\"" + hobbies + "\"}";
}
}
- 4.3调用
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
person.setAge("11");
person.setHeight("172");
person.setName("xiaoghong");
ArrayList<String> hobbies = new ArrayList<String>();
hobbies.add("游泳");
person.setHobbies(hobbies);
Person person2 = (Person) person.clone();
person2.setAge("15");
person2.getHobbies().add("篮球");
System.out.println("person "+person.toString());
System.out.println("person "+ person2.toString());
Person2 person3 = new Person2();
person3.setAge("11");
person3.setHeight("172");
person3.setName("xiaoghong");
ArrayList<String> hobbies3 = new ArrayList<String>();
hobbies3.add("游泳");
person3.setHobbies(hobbies);
Person2 person4 = new Person2(person3);
person4.getHobbies().add("羽毛球");
System.out.println("person "+person3.toString());
System.out.println("person "+ person4.toString());
}
}
- 4.3运行结果
person {"name":"xiaoghong","age":"11","weight":"null","height":"172","hobbies":"[游泳]"}
person {"name":"xiaoghong","age":"15","weight":"null","height":"172","hobbies":"[游泳, 篮球]"}
person {"name":"xiaoghong","age":"11","weight":"null","height":"172","hobbies":"[游泳]"}
person {"name":"xiaoghong","age":"11","weight":"null","height":"172","hobbies":"[游泳, 羽毛球]"}
5.Android中应用场景
Bundle类实现了Cloneable接口
public Object clone() {
return new Bundle(this);
}
public Bundle(Bundle b) {
super(b);
mHasFds = b.mHasFds;
mFdsKnown = b.mFdsKnown;
}
Intent也实现了Cloneable接口
@Override
public Object clone() {
return new Intent(this);
}
public Intent(Intent o) {
this.mAction = o.mAction;
this.mData = o.mData;
this.mType = o.mType;
this.mPackage = o.mPackage;
this.mComponent = o.mComponent;
this.mFlags = o.mFlags;
this.mContentUserHint = o.mContentUserHint;
if (o.mCategories != null) {
this.mCategories = new ArraySet<String>(o.mCategories);
}
if (o.mExtras != null) {
this.mExtras = new Bundle(o.mExtras);
}
if (o.mSourceBounds != null) {
this.mSourceBounds = new Rect(o.mSourceBounds);
}
if (o.mSelector != null) {
this.mSelector = new Intent(o.mSelector);
}
if (o.mClipData != null) {
this.mClipData = new ClipData(o.mClipData);
}
}
6.总结
优点
(1)原型模式是在内存中二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量对象时,原型模式可能更好的体现其优点。
(2)还有一个重要的用途就是保护性拷贝,也就是对某个对象对外可能是只读的,为了防止外部对这个只读对象的修改,通常可以通过返回一个对象拷贝的形式实现只读的限制。
缺点:
(1)这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的,在实际开发中应该注意这个潜在问题。优点是减少了约束,缺点也是减少了约束,需要大家在实际应用时考虑。
(2)通过实现Cloneable接口的原型模式在调用clone函数构造实例时并不一定比通过new操作速度快,只有当通过new构造对象较为耗时或者说成本较高时,通过clone方法才能够获得效率上的提升。
把自己学习设计模式的过程记成笔记,方便自己随时查看,如有错误,欢迎指出,谢谢!