设计模式:6-原型模式:Prototype
2020-05-21 本文已影响0人
大栗几
文章来源本人的博客:http://codelifeliwan.github.io/ 转载请注明出处
查看[设计模式]系列内容请点击:https://www.jianshu.com/nb/45937362
定义:(Prototype)
用原型实例制定创建对象的种类,并且通过复制这些原型对象创建新的对象
理解:
就是根据一个对象复制出来另一个对象
方法:
在Object类中有一个clone()方法,但是是protected的,可以选择覆写Object类中的clone()方法,不使用Object的clone()方法,如果需要使用Object的clone()方法则必须实现Cloneable接口。
实现Cloneable接口并覆写Object的clone()方法,在覆写的方法中调用super.clone()复制,需要注意的是,Object中的clone()是按位复制,就是复制的是完全一样的对象。
代码说明:
package com.codelifeliwan.prototype1;
public class ClassA {
private int a;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
@Override
public ClassA clone() {
ClassA a = new ClassA(); // 自己创建对象
a.setA(this.getA()); // 设置对象参数
return a;
}
}
package com.codelifeliwan.prototype1;
public class ClassB implements Cloneable{
private int a;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
@Override
public ClassB clone() {
try {
// 在没有实现Cloneable接口的情况下调用super.clone()会造成异常
return (ClassB) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
package com.codelifeliwan.prototype1;
public class Main {
public static void main(String args[]) {
ClassA a1 = new ClassA();
a1.setA(10);
ClassA a2 = a1.clone();
System.out.println("a1:" + a1.getA());
System.out.println("a2:" + a2.getA());
a2.setA(20);
System.out.println("a1:" + a1.getA());
System.out.println("a2:" + a2.getA());
System.out.println("\n==============美丽的分割线=================\n");
ClassB b1 = new ClassB();
b1.setA(10);
// System.out.println(b1.clone().toString());
ClassB b2 = b1.clone();
System.out.println("b1:" + b1.getA());
System.out.println("b2:" + b2.getA());
b2.setA(20);
System.out.println("b1:" + b1.getA());
System.out.println("b2:" + b2.getA());
}
}
package com.codelifeliwan.prototype2;
public interface IClassA extends Cloneable {
}
package com.codelifeliwan.prototype2;
public class ClassA implements IClassA {
private String str1;
private String str2;
public String getStr1() {
return str1;
}
public void setStr1(String str1) {
this.str1 = str1;
}
public String getStr2() {
return str2;
}
public void setStr2(String str2) {
this.str2 = str2;
}
public ClassA clone() {
ClassA a = null;
try {
a = (ClassA) super.clone();
a.setStr1("jascgudc");
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return a;
}
}
package com.codelifeliwan.prototype2;
public class Client {
public static void main(String args[]) {
ClassA a1 = new ClassA();
a1.setStr1("hello");
a1.setStr2("world");
ClassA a2 = a1.clone();
System.out.println("a1:" + a1.getStr1() + " " + a1.getStr2());
System.out.println("a2:" + a2.getStr1() + " " + a2.getStr2());
System.out.println("\n=================美丽的分割线=============\n");
a2.setStr2("wanli");
System.out.println("a1:" + a1.getStr1() + " " + a1.getStr2());
System.out.println("a2:" + a2.getStr1() + " " + a2.getStr2());
}
}
适用场景:
- 性能和安全要求场景:通过new一个对象需要繁琐的数据准备或者访问权限等,可以直接克隆一个对象
- 资源优化场景:对象初始化的时候需要消耗非常多的资源,可以考虑直接克隆一个对象
- 一个对象有多个修改者场景:一个对象可能有多个访问者访问,且访问者可能修改对象,则可以为每个访问者克隆一个对象
在Spring框架中,我们使用@Repository
注解等方式默认是单例模式,只创建一个对象全局共用,但是可以加上@Scope(“prototype”)
使其为原型模式,每次使用都会创建新的实例