原型模式(Prototype):
未使用设计模式代码:
package Prototype.NoPattern;
public class Resume {
private String name;//姓名
private int age; //年龄
private String sex; //性别
private String timeAree; //工作时长
private String company; //公司
public void setPersonInfo(int age,String sex){//设置个人信息
this.age = age;
this.sex = sex;
}
public void setWorkExperience(String timeAree,String company){//设置工作经历
this.timeAree = timeAree;
this.company = company;
}
public void display(){//显示
System.out.println(name+" "+age+" "+sex);
System.out.println("工作经历:"+company +";工作年限:"+timeAree);
}
public Resume(String name) {
super();
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
Resume a = new Resume("大鸟");
a.setPersonInfo(25, "男");
a.setWorkExperience("2008-2010", "xx公司");
Resume b = new Resume("大鸟");
b.setPersonInfo(25, "男");
b.setWorkExperience("2008-2010", "xx公司");
Resume c = new Resume("大鸟");
c.setPersonInfo(25, "男");
c.setWorkExperience("2008-2010", "xx公司");
a.display();
b.display();
c.display();
}
}
按照大鸟的话来说,这就相当于 在以前没有打印的年代,手写代码一样。 当需要三份简历的时候,就需要些三次,如果需要二十份,则需要实例化二十次。而且当有一个地方出现错误的时候,需要改20处。很显然这样是很不好的。于是引出了设计模式:原型模式。
原型模式(Prototype):
原型模式UML类图:
源代码:
public interface Prototype extends Cloneable{//抽象克隆对象
public Object clone();
}
public class ConcretePrototype implements Prototype{//具体克隆对象
public Object clone(){//最简单的克隆方法,由于没有属性就不复制值了
Prototype prototype = new ConcretePrototype();
return prototype;
}
}
public class Client {
private Prototype prototype;//持有需要使用的原型接口对象
public Client(Prototype prototype) {//构造方法,需要传入一个需要克隆的对象
super();
this.prototype = prototype;
}
public Prototype operation(){
ConcretePrototype concretePrototype =(ConcretePrototype) prototype.clone();
return concretePrototype ;
}
}
Java中的克隆:
Java的所有类都是从java.lang.Object类继承而来的,而Object类提供protected Object clone()方法对对象进行复制,子类当然也可以把这个方法置换掉,提供满足自己需要的复制方法。对象的复制有一个基本问题,就是对象通常都有对其他的对象的引用。当使用Object类的clone()方法来复制一个对象时,此对象对其他对象的引用也同时会被复制一份
Java语言提供的Cloneable接口只起一个作用,就是在运行时期通知Java虚拟机可以安全地在这个类上使用clone()方法。通过调用这个clone()方法可以得到一个对象的复制。由于Object类本身并不实现Cloneable接口,因此如果所考虑的类没有实现Cloneable接口时,调用clone()方法会抛出CloneNotSupportedException异常。
克隆满足的条件:
clone()方法将对象复制了一份并返还给调用者。所谓“复制”的含义与clone()方法是怎么实现的。一般而言,clone()方法满足以下的描述:
1.在派生类中覆盖基类的clone()方法,并声明为public【Object类中的clone()方法为protected的】。
2.在派生类的clone()方法中,调用super.clone()。
3.在派生类中实现Cloneable接口。
克隆后的对象与原对象比较:
(1)对任何的对象x,都有:x.clone()!=x。换言之,克隆对象与原对象不是同一个对象。
(2)对任何的对象x,都有:x.clone().getClass() == x.getClass(),换言之,克隆对象与原对象的类型一样。
(3)如果对象x的equals()方法定义其恰当的话,那么x.clone().equals(x)应当成立的。
在JAVA语言的API中,凡是提供了clone()方法的类,都满足上面的这些条件。JAVA语言的设计师在设计自己的clone()方法时,也应当遵守着三个
条件。一般来说,上面的三个条件中的前两个是必需的,而第三个是可选的。
利用原型模式实现简历打印:
public class Resume implements Cloneable{ private String name; private int age; private String sex; private String timeAree; private String company; public void setPersonInfo(int age,String sex){ this.age = age; this.sex = sex; } public void setWorkExperience(String timeAree,String company){ this.timeAree = timeAree; this.company = company; } public void display(){ System.out.println(name+" "+age+" "+sex); System.out.println("工作经历:"+company +";工作年限:"+timeAree); } public Resume() { super(); } public Resume(String name) { super(); this.name = name; } public Resume(String name, int age, String sex, String timeAree, String company) { this.name = name; this.age = age; this.sex = sex; this.timeAree = timeAree; this.company = company; }
}public Object clone() throws CloneNotSupportedException{ return super.clone(); }
public class Client {//打印方法,通过该方法实现克隆简历,相当于打印功能 Resume resume ; public Client(Resume resume) { super(); this.resume = resume; } public Resume getResume() throws CloneNotSupportedException{ return (Resume)resume.clone(); } }
public class Main { public static void main(String[] args) throws CloneNotSupportedException{ Resume resume = new Resume("小菜"); resume.setPersonInfo(18, "男"); resume.setWorkExperience("2016-2017", "XX公司"); Client c = new Client(resume); Resume resume2=c.getResume(); Resume resume3=c.getResume(); resume.display(); resume2.display(); resume3.display(); } }
深克隆与潜克隆:
A:浅复制(浅克隆): 浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
b:深复制(深克隆):深复制把要复制的对象所引用的对象都复制了一遍。浅克隆示例:
public class Dept implements Cloneable{//部门
String id;
String name;
public Dept(String id, String name) {
this.id = id;
this.name = name;
}
public Dept clone() throws CloneNotSupportedException{
return (Dept) super.clone();
}
}
public class Emp implements Cloneable{
String name ;
String id;
Dept dept;
public Emp(String name, String id, Dept dept) {
super();
this.name = name;
this.id = id;
this.dept = dept;
}
public Emp clone() throws CloneNotSupportedException{
return (Emp) super.clone();
}
}
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Dept d = new Dept("1", "技术部");
Dept d2 = d.clone();
System.out.println(d == d2);
Emp e = new Emp("小明", "1", d);
Emp e2 = e.clone();
System.out.println(e==e2);
System.out.println(e.dept==e2.dept);
}
}
结果为:
false
false
true
public class Emp implements Cloneable{
String name ;
String id;
Dept dept;
public Emp(String name, String id, Dept dept) {
super();
this.name = name;
this.id = id;
this.dept = dept;
}
public Emp clone() throws CloneNotSupportedException{
Emp emp = (Emp) super.clone();
emp.dept=dept.clone();
return emp;
}
}
通过序列化实现深克隆:
public class Dept implements Serializable{
private static final long serialVersionUID = 6798532648769041110L;
String id;
String name;
public Dept(String id, String name) {
this.id = id;
this.name = name;
}
}
public class Emp implements Serializable{
String name ;
String id;
Dept dept;
public Emp(String name, String id, Dept dept) {
super();
this.name = name;
this.id = id;
this.dept = dept;
}
public Object deepClone() throws Exception{
//将该对象序列化成流,因为写在流里的是对象的一个拷贝,
//而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//将流序列化成对象
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
public class Main {
public static void main(String[] args) throws Exception {
Dept d = new Dept("1", "技术部");
Emp e = new Emp("小明", "1", d);
Emp e2 = (Emp) e.deepClone();
System.out.println(e==e2);
System.out.println(e.dept==e2.dept);
}
}
此时,输出的结果一样是false,false.