2、
抽象工厂通常是使用“工厂方法”模式实施的,另一种方式是使用“原型”模式(下面会着重阐述原型模式)。抽象工厂与之前的两种模型的原理基本相似,这里就不做重复解释了。
3、
原型模式,之前的“工厂方法”和“抽象工厂”模式都使客户机对象可以通过调用指定的方法创建相应的类的实例,而不必指定要实例化的具体类。而原型模式可以用另一种不同的更加灵活的方法来实现相同的功能。原型模式的原理是先创建一个对象,然后将其指定为原型对象,通过复制原型对象并进行所需的修改创建其他对象。通俗的理解原型模式便如简历表,在申请不同的公司的职位时你是在那个基础的简历表的基础上正对不同的公司进行个性化的修改。从它原理中我们便可以看出它的实现需要有一种复制的方法,那怎么来实现它呢?且听我慢慢道来:对象被复制被分为:浅复制和深复制。在默认情况下,所有的java对象都会继承顶层java.long.Object类的内置clone()方法。内置clone()方法将原对象的复制项创建为浅复制项。
浅复制项与深复制项的区别可以从两个字开始理解——“会”和“不会”——浅复制项即对象的原顶层对象与所有原始成员都会被复制但顶层对象包含的任何底层对象都不会被复制,仅复制这些对象的引用(使得原对象和复制对象引用底层对象的同一个复制项)。深复制项即对象原顶层对象与所有原始成员都会被复制而且顶层对象包含的任何底层对象也会被复制。这样说是不是有点难以理解?那我们现在就形象化的用两个突来表示:
originalobject |
Nonobjectreferences Objectreferences-1 |
cloneobject |
copyofNonobjectreferences copyofObjectreferences-1 |
对应于(共享)同一个
Object-1 |
浅复制
cloneobject |
copyofNonobjectreferences copyofObjectreferences-1 |
originalobject |
Nonobjectreferences Objectreferences-1 |
对应于 对应于
Object-1 |
copyofObject-1 |
深复制
下面先来具体分析浅复制:
设计一个简单的学生选选修课成绩的例子:
创建学生选选修课类Student的实例:
public class Student implements Cloneable{
private Course course;
private String name;
public Course getCourse(){
return course;
}
public String getName(){
return name;
}
public void setName(String s){
name=s;
}
public Student(String s,String t){
name=s;
course=new Course(t);
}
/**在类实施Cloneable接口后它应使用公共方法public Object clone()
覆盖Object.clone方法,在不实施Cloneable接口的对象上调用clone方法时,
将抛出异常CloneNotSupportedException
*/
public Object clone(){
try{
return super.clone();
}catch(CloneNotSupportedException e){
return null;
}
}
class Course{
private String name;
public String getName(){
return name;
}
public void setName(String s){
name=s;
}
public Course(String s){
name=s;
}
}
}
为此类对象创建复制项,并更改其属性值,测试显示不同阶段其属性的值:
public class ShallowCopyTest {
public static void main(String args[]){
Student ss=new Student("王亮","大学英语");
System.out.println("original(original value is)"+ss.getName()+"_"+
ss.getCourse().getName());
Student ss1=(Student)ss.clone();
System.out.print("clone(before change is)"+ss1.getName()+"_"+
ss1.getCourse().getName()+"\r\n");
ss1.setName("李凡");
ss1.getCourse().setName("高等数学");
System.out.print("clone(after change is)"+ss1.getName()+"_"
+ss1.getCourse().getName()+"\r\n");
System.out.println("original(after change is)"+ss.getName()+"_"+
ss.getCourse().getName());
}
此程序运行结果为:
original(original value is)王亮_大学英语
clone(before change is)王亮_大学英语
clone(after change is)李凡_高等数学
original(after change is)王亮_高等数学
再来看看深复制:
Student类:
public class Student implements Cloneable{
private Course course;
private String name;
public Course getCourse(){
return course;
}
public String getName(){
return name;
}
public void setName(String s){
name=s;
}
public Student(String s,String t){
name=s;
course=new Course(t);
}
public Object clone(){
Student ss=new Student(name,course.getName());
return ss;
}
class Course{
private String name;
public String getName(){
return name;
}
public void setName(String s){
name=s;
}
public Course(String s){
name=s;
}
}
}
DeepCopyTest类:
public class DeepCopyTest {
public static void main(String args[]){
Student ss=new Student("王亮","大学英语");
System.out.println("original(original value is)"+ss.getName()+"_"+
ss.getCourse().getName());
Student ss1=(Student)ss.clone();
System.out.print("clone(before change is)"+ss1.getName()+"_"+
ss1.getCourse().getName()+"\r\n");
ss1.setName("李凡");
ss1.getCourse().setName("高等数学");
System.out.print("clone(after change is)"+ss1.getName()+"_"
+ss1.getCourse().getName()+"\r\n");
System.out.println("original(after change is)"+ss.getName()+"_"+
ss.getCourse().getName());
}
}
运行结果为:
original(original value is)王亮_大学英语
clone(before change is)王亮_大学英语
clone(after change is)李凡_高等数学
original(after change is)王亮_大学英语
由这两段代码的测试结果可以很明确的看出浅复制由于发生了复制共享所以发生复制后原来的对象的属性值变为了共享的值,而深复制虽发生了复制但不共享所以发生复制后原来的对象的属性值仍为原来的值。