zoukankan      html  css  js  c++  java
  • 设计模式(十二)——原型模式

    1.描述

    用原型实例制定创建对象的种类,并且通过复制这些原型创建的对象。

    2.模式的使用

    ·抽象原型(Prototype):一个接口。负责定义对象复制自身的方法。

    ·具体原型(ConcretePrototype):实现Prototype接口的类。具体原型实现抽象原型中的方法,以便所创建的对象调用该方法复制自己。

    3.使用情景

    ·程序需要从一个对象出发,得到若干和其状态相同,并可独立变化其状态的对象时。

    ·当对象的创建需要独立于他的构建和表示时。

    ·一个类创建实例状态不是很多,那么就可以将这个类的一个实例定义为原型,那么可以通过复制该原型得到新的实例,这可能比重新使用该类的构造方法创建实例方便。

    4.优点

    ·复制已有实例可以提高效率时。

    ·可以动态保存当前对象状态。在运行时,可以随时使用对象流保存当前对象的一个复制。

    ·可以在运行时创建新的对象,无需创建一系列类和继承结构。

    ·可以动态添加、删除原型的复制品

    5.UML

    6案例

    clone()方法

    java.lang包中的Object类提供了一个权限是protected的用于复制对象的clone()方法。java中所有的类都继承了该方法,但由于该方法是protected的,如果一个对象想使用该方法得到自己的一个复制,就必须保证自己与所在的类在同一个包中,这显然是不可能的,因为java不允许用户将包名命名为java.lang。

    为了能让一个对象使用clone()方法,创建该对象的类可以重写clone方法(super即可),并将权限设为public。

    另外,当对象调用Object中的clone()方法时,JVM会逐个复制对象的成员变量,然后创建一个新的对象返回,所以JVM要求调用clone()方法的对象必须实现Cloneable接口。Cloneable接口中没有任何方法,其唯一的作用就是让JVM知道实现该接口的对象可以被复制。

     1 package 原型模式;
     2 
     3 public class test1 {
     4 
     5     public static void main(String[] args) {
     6         Circle circle = new Circle();
     7         circle.setRadius(11.22);
     8         try {
     9             Circle circleCopy = (Circle) circle.clone();
    10             System.out.println("circlr中的数据:" + circle.getRadius());
    11             System.out.println("circlrCopy中的数据:" + circleCopy.getRadius());
    12         } catch (CloneNotSupportedException e) {
    13             // TODO Auto-generated catch block
    14             e.printStackTrace();
    15         }
    16     }
    17 
    18 }
    19 
    20 class Circle implements Cloneable{
    21     private double radius;
    22 
    23     public double getRadius() {
    24         return radius;
    25     }
    26 
    27     public void setRadius(double radius) {
    28         this.radius = radius;
    29     }
    30     
    31     public Object clone() throws CloneNotSupportedException{
    32         Object object = super.clone();
    33         return object;
    34     }
    35 }

    深度克隆

    Object中的clone()方法将复制对象中的值来创建新对象,如果当前对象拥有的成员变量是一个对象,那么clone()方法将会复制当前对象的引用,并没有复制该对象的所拥有的变量。所以在进行克隆时,必须对对象所包含的其他对象进行复制。

     1 package 原型模式;
     2 
     3 public class test2 {
     4 
     5     public static void main(String[] args) {
     6         A a = new A(1.1);
     7         B b = new B(a, 2);
     8         try {
     9             B bCopy = (B) b.clone();
    10             System.out.println("a中的属性:" + a.a);
    11             System.out.println("b中的属性 int b:" + b.b);
    12             System.out.println("b中的属性 A a:" + b.a.getClass());
    13             System.out.println("bCopy中的属性 int b:" + bCopy.b);
    14             System.out.println("bCopy中的属性 A a:" + bCopy.a.getClass());
    15             //分别改变对象的属性
    16             b.a.a = 2.2;
    17             System.out.println("b中的属性 A a的属性:" + b.a.a);
    18             bCopy.a.a = 3.3;
    19             System.out.println("bCopy中的属性 A a的属性:" + bCopy.a.a);
    20         } catch (CloneNotSupportedException e) {
    21             // TODO Auto-generated catch block
    22             e.printStackTrace();
    23         }
    24     }
    25 
    26 }
    27 
    28 class A implements Cloneable{
    29     double a;
    30     A(double a){
    31         this.a = a;
    32     }
    33     
    34     public Object clone() throws CloneNotSupportedException{
    35         Object o = super.clone();
    36         return o;
    37     }
    38 }
    39 
    40 class B implements Cloneable{
    41     int b;
    42     A a;//a对象必须重写了clone()方法
    43     B(A a, int b){
    44         this.a = a;
    45         this.b = b;
    46     }
    47     
    48     public Object clone() throws CloneNotSupportedException{
    49         B b = (B)super.clone();
    50         b.a = (A)a.clone();
    51         return b;
    52         
    53     }
    54 }

    Serializable接口与克隆对象

     相对于clone()方法,java提供了一种简单的复制方案,使用Serializable接口和对象流来进行复制。

    这种方法需要保证被复制的对象即其成员变量中的对象都必须实现了Serializable接口。

     1 package 原型模式;
     2 
     3 import java.io.ByteArrayInputStream;
     4 import java.io.ByteArrayOutputStream;
     5 import java.io.IOException;
     6 import java.io.ObjectInputStream;
     7 import java.io.ObjectOutputStream;
     8 import java.io.Serializable;
     9 
    10 public class test3 {
    11 
    12     public static void main(String[] args) {
    13         Goat goat = new Goat();
    14         goat.setColor("白色");
    15         Goat goatCopy = (Goat)goat.clone();
    16         System.out.println(goatCopy.hashCode());//完全复制后
    17         System.out.println(goatCopy.getColor());
    18         goatCopy.setColor("黑色");
    19         System.out.println(goat.hashCode());
    20         System.out.println(goatCopy.hashCode());
    21     }
    22 
    23 }
    24 
    25 class Goat implements Serializable{
    26     String color;
    27 
    28     public String getColor() {
    29         return color;
    30     }
    31 
    32     public void setColor(String color) {
    33         this.color = color;
    34     }
    35     
    36     public Object clone() {
    37         Object o = null;
    38         ByteArrayOutputStream out1 = new ByteArrayOutputStream();
    39         try {
    40             ObjectOutputStream out2 =  new ObjectOutputStream(out1);
    41             out2.writeObject(this);//将对象写入输出流
    42             ByteArrayInputStream in1 = new ByteArrayInputStream(out1.toByteArray());
    43             ObjectInputStream in2 =  new ObjectInputStream(in1);
    44             o = in2.readObject();
    45         } catch (IOException e) {
    46             // TODO Auto-generated catch block
    47             e.printStackTrace();
    48         } catch (ClassNotFoundException e) {
    49             // TODO Auto-generated catch block
    50             e.printStackTrace();
    51         }
    52         
    53         return o;
    54     }
    55 }

  • 相关阅读:
    Java 9将采用新的版本字符串格式
    Hadoop单机伪分布式
    Hadoop JAVA 开发说明
    Java 批量插入数据(Oracle)
    Myeclipse 的hadoop环境搭建
    [LeetCode] 136. Single Number 单独数
    [LeetCode] 89. Gray Code 格雷码
    [LeetCode] 209. Minimum Size Subarray Sum 最短子数组之和
    [LeetCode] 211. Add and Search Word
    [LeetCode] 152. Maximum Product Subarray 求最大子数组乘积
  • 原文地址:https://www.cnblogs.com/cxy2016/p/7670229.html
Copyright © 2011-2022 走看看