• 设计模式之prototype原型模式


    definition

    Specify the kind of objects to create using a prototypical instance, and create new objects by copying this prototype

    participants

        The classes and/or objects participating in this pattern are:

    • Prototype  (ColorPrototype)
      • declares an interface for cloning itself
    • ConcretePrototype  (Color)
      • implements an operation for cloning itself
    • Client  (ColorManager)
      • creates a new object by asking a prototype to clone itself

    用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

    public abstract class AbstractSpoon implements Cloneable{
      String spoonName;
    
      public void setSpoonName(String spoonName) {
                this.spoonName = spoonName;
          }
      public String getSpoonName() {return this.spoonName;}
    
      public Object clone(){
        Object object = null;
        try {
          object = super.clone();
        } catch (CloneNotSupportedException exception) {
          System.err.println("AbstractSpoon is not Cloneable");
        }
        return object;
      }
    }

    个具体实现(ConcretePrototype):

    public class SoupSpoon extends AbstractSpoon{
      public SoupSpoon(){
        setSpoonName("Soup Spoon");
      }
    }

    调用Prototype模式很简单:

    AbstractSpoon spoon = new SoupSpoon();
    AbstractSpoon spoon2 = spoon.clone();

    当然也可以结合工厂模式来创建AbstractSpoon实例。

    在Java中Prototype模式变成clone()方法的使用,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。

    AbstractSpoon实现clone时调用super.clone()的原理:

    ava super.clone   实现Cloneable接口

    首先,如果允许本来被克隆,需要实现 实现Cloneable接口

    并且重写clone方法,且方法最好为public,这样方便别人调用

    其中:super.clone并不是简单的说成是调用父类的clone方法,这样的话你很难想通,为什么调用父类的clone,对吧?

    因为Object的clone方法使用了RTTI(运行时类型识别)机制,可以动态的找到目前正在调用clone方法的那个引用,并找到它指向的对象,然后根据这个对象的大小去申请内存空间,然后进行bitwise(逐位)的复制, 将该对象的内存空间完全复制到新的空间中去,

    从而达到克隆的目的.

    即,谁调用clone方法,就克隆这引用指向的对象

     子类没有clone方法,使用this.clone()则直接异常,,因为是子类继承Object的 

    比如你有一个Student类实现了Cloneable接口,重写了clone方法,但是重写的clone方法里的执行super.clone,并不是说和自身无关,

     例如:     Student stu=new student();

                     Student stu1=(Student)stu.clone();

    当执行stu.clone();时候,虽然clone方法里面执行的是super.clone(),但是Object的clone方法会寻找当前正在调用clone方法的那个引用,这里这个引用就是stu,然后自动的去找stu指向的对象,然后进行逐位赋值,从而达到克隆的目的,

    还有继承的时候,A类实现了Cloneable接口,重写了了clone方法,那继承A类的类就不必实现Cloneable接口以及重写clone方法了,因为A类已经这么做了。而当子类调用clone方法的时候,是根据调用clone方法的当前引用去克隆的,

    还是那句话,谁调用clone方法,就克隆当前引用指向的对象。

    说明: 
    克隆必须满足的条件: 
    a.对任何的对象x,都有:x.clone() != x,即克隆对象与原对象不是同一个对象。 
    b.对任何的对象x,都有:x.clone().getClass() == x.get getClass(),即克隆对象与原对象的类型是一样的。 c.如果对象x的equals()方法定义恰当的话,那么x.clone().equals(x)应当是成立的。 
    在java中实现clone()应该满足这三个条件。 

    浅复制复制了值类型对象,对于引用类型对象,只复制了引用,它指向原来引用的对象。Java中clone为浅复制。 
    深复制对值类型和引用类型的对象都生成一份新的拷贝. Java中可以通过串行化来进行深复制,前提是对象以及对象内部所引用的对象都是可串行化的,否则需要考虑将那些不可串行化的对象可否设为transient,排除     在复制过程之外。

  • 相关阅读:
    PHP之简单实现MVC框架
    socket泄露的问题
    gdb 调试多线程
    MMAP和DIRECT IO区别
    三年回首:C基础
    定时器管理:nginx的红黑树和libevent的堆
    strsep和strtok_r替代strtok
    缓存穿透和缓存失效
    mmap为什么比read/write快(兼论buffercache和pagecache)
    B+Tree和MySQL索引分析
  • 原文地址:https://www.cnblogs.com/youxin/p/2950190.html
Copyright © 2020-2023  润新知