原型模式 - 创建者模式

来源:互联网 发布:java script 编辑:程序博客网 时间:2024/05/29 03:15
个人理解:    

模式类型:

    Prototype 原型模式 - 创建者模式

意图:
    specifying the kind of objects to create using a prototypical instance
    creating new objects by copying this prototype

    
概述:
    原型模式是一种创建型设计模式,它通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的.
    原型模式多用于创建复杂的或者耗时的实例, 因为这种情况下,复制一个已经存在的实例可以使程序运行更高效,或者创建值相等,只是命名不一样的同类数据.

    
    原型模式中的拷贝分为"浅拷贝"和"深拷贝":
    浅拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象.
    深拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制.

    
    注:使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,因此不会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。还记得单例模式吗?单例模式中,只要将构造方法的访问权限设置为private型,就可以实现单例。但是clone方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的,在使用时要特别注意。
    
    不是基本类型,所以成员变量不会被拷贝,需要我们自己实现深拷贝。
    深拷贝与浅拷贝问题中,会发生深拷贝的有java中的8中基本类型以及他们的封装类型,另外还有String类型。其余的都是浅拷贝。


角色:

Client - creates a new object by asking a prototype to clone itself.
Prototype - declares an interface for cloning itself.
ConcretePrototype - implements the operation for cloning itself.

模式的应用场景:
       使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
       使用原型模式的另一个好处是简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。
       因为以上优点,所以在需要重复地创建相似对象时可以考虑使用原型模式。比如需要在一个循环体内创建对象,假如对象创建过程比较复杂或者循环次数很多的话,使用原型模式不但可以简化创建过程,而且可以使系统的整体性能提高很多。

结构图:



模式的优缺点:



注意事项:
    使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,因此不会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。还记得单例模式吗?单例模式中,只要将构造方法的访问权限设置为private型,就可以实现单例。但是clone方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的,在使用时要特别注意。
    深拷贝与浅拷贝。Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。
   
代码(其实读UML图要比代码还要一目了然):


1、Shape.java

public abstract class Shape implements Cloneable {      private String id;   protected String type;      abstract void draw();      public String getType(){      return type;   }      public String getId() {      return id;   }      public void setId(String id) {      this.id = id;   }      public Object clone() {      Object clone = null;            try {         clone = super.clone();               } catch (CloneNotSupportedException e) {         e.printStackTrace();      }            return clone;   }}

2、Rectangle.java

public class Rectangle extends Shape {   public Rectangle(){     type = "Rectangle";   }   @Override   public void draw() {      System.out.println("Inside Rectangle::draw() method.");   }}

Square.java

public class Square extends Shape {   public Square(){     type = "Square";   }   @Override   public void draw() {      System.out.println("Inside Square::draw() method.");   }}

Circle.java

public class Circle extends Shape {   public Circle(){     type = "Circle";   }   @Override   public void draw() {      System.out.println("Inside Circle::draw() method.");   }}

3、ShapeCache.javaCreate a class to get concrete classes from database and store them in a Hashtable.

import java.util.Hashtable;public class ShapeCache {   private static Hashtable<String, Shape> shapeMap  = new Hashtable<String, Shape>();   public static Shape getShape(String shapeId) {      Shape cachedShape = shapeMap.get(shapeId);      //---这句是重点!!,返回的是对象的克隆!----      return (Shape) cachedShape.clone();   }   // for each shape run database query and create shape   // shapeMap.put(shapeKey, shape);   // for example, we are adding three shapes      public static void loadCache() {      Circle circle = new Circle();      circle.setId("1");      shapeMap.put(circle.getId(),circle);      Square square = new Square();      square.setId("2");      shapeMap.put(square.getId(),square);      Rectangle rectangle = new Rectangle();      rectangle.setId("3");      shapeMap.put(rectangle.getId(), rectangle);   }}

4、PrototypePatternDemo.javaPrototypePatternDemo uses ShapeCache class to get clones of shapes stored in aHashtable.

public class PrototypePatternDemo {   public static void main(String[] args) {      ShapeCache.loadCache();      Shape clonedShape = (Shape) ShapeCache.getShape("1");      System.out.println("Shape : " + clonedShape.getType());      Shape clonedShape2 = (Shape) ShapeCache.getShape("2");      System.out.println("Shape : " + clonedShape2.getType());      Shape clonedShape3 = (Shape) ShapeCache.getShape("3");      System.out.println("Shape : " + clonedShape3.getType());   }}

5、输出:

Shape : CircleShape : SquareShape : Rectangle


--===========================深拷备的分割线===============================--

深拷备是2种方法:

1、利用super.clone(); 后,再给不属于基本变量的类型属性赋值

package com.lee.desingerPattener23.prototype.example3;class Professor implements Cloneable{      String name;      int age;      Professor(String name,int age){          this.name=name;          this.age=age;      }      public Object clone(){          Object o=null;          try{              o=super.clone();          }catch(CloneNotSupportedException e){              System.out.println(e.toString());          }          return o;      }  }  public class Student implements Cloneable{      String name;      int age;      Professor p;      Student(String name,int age,Professor p){          this.name=name;          this.age=age;          this.p=p;      }      public Object clone(){          Student o=null;          try{              o=(Student)super.clone();          }catch(CloneNotSupportedException e){              System.out.println(e.toString());          }         // --- 重点!:调用Professor类的clone()方法实现深拷贝 ---         o.p=(Professor)this.p.clone();          return o;      }          public static void main(String[] args){          Professor p=new Professor("wangwu",50);          Student s1=new Student("zhangsan",18,p);          Student s2=(Student)s1.clone();          s2.p.name="lisi";         s2.p.age=30;         //学生1的教授不改变         System.out.println("name="+s1.p.name+","+"age="+s1.p.age);       System.out.println("name="+s2.p.name+","+"age="+s2.p.age);    }  }  


2、利用序列化实现深度拷贝

把对象写到流里的过程是串行化(Serilization)过程,又叫对象序列化,而把对象从流中读出来的(Deserialization)过程叫反序列化。应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里,再从流里读出来便可以重建对象。


package com.lee.desingerPattener23.prototype.example3;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.OptionalDataException;import java.io.Serializable;class Profess implements Serializable{      String name;      int age;      Profess(String name,int age){          this.name=name;          this.age=age;      }  }  public class StudentDeep implements Serializable{      String name;      int age;      Profess p;      StudentDeep(String name,int age,Profess p){          this.name=name;          this.age=age;          this.p=p;      }      public Object deepClone() throws IOException,OptionalDataException,ClassNotFoundException{    Object o = null;    try{    //将对象写到流里      ByteArrayOutputStream bo=new ByteArrayOutputStream();      ObjectOutputStream oo=new ObjectOutputStream(bo);      oo.writeObject(this);// object of studnet      oo.close();    //从流里读出来      ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());      ObjectInputStream oi=new ObjectInputStream(bi);      o = oi.readObject();    oi.close();    }catch (IOException e)  {              e.printStackTrace();          } catch (ClassNotFoundException e){              e.printStackTrace();          }          return o;     }       public static void main(String[] args) throws OptionalDataException, ClassNotFoundException, IOException{          Profess p=new Profess("wangwu",50);          StudentDeep s1=new StudentDeep("zhangsan",18,p);          StudentDeep s2=(StudentDeep)s1.deepClone();          s2.p.name="lisi";          s2.p.age=30;       //学生1的教授不改变       System.out.println("name="+s1.p.name+","+"age="+s1.p.age);     System.out.println("name="+s2.p.name+","+"age="+s2.p.age);     }  }  

输出结果:

name=wangwu,age=50name=lisi,age=30


所有模式:
     创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
    行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
    补充模式:空对象模式


参考/转自:

http://blog.csdn.net/zhengzhb/article/details/7393528
http://www.tutorialspoint.com/design_pattern/prototype_pattern.htm
http://www.oodesign.com/prototype-pattern.html
http://blog.csdn.net/chjttony/article/details/7477346


转载请注明:http://blog.csdn.net/paincupid/article/details/46860283



0 0
原创粉丝点击