Prototype mode

Foreword

Benpian is a design pattern study notes One of the articles, such as interested in other modes, you can find from that address design pattern study notes summary address

1. prototype mode

A plurality of identical objects can be cloned by a prototype object, which is sometimes called prototype pattern

2. Definitions

Prototype model (Prototype Pattern): a prototype to create an object instance of the specified type, and create new objects by copying the prototype .

Prototype model is a schema object creation

3. Works

A prototype will be launched to create the object passed to the object that you want to launch their own copies created the prototype object is achieved by requesting the creation process. Since the software system, we often encounter the need to create more of the same or similar circumstances object, so frequently used in prototype mode of real development is still very high.

Prototype model is an "alternative" created schema, created is the prototype clone object factory class itself, factory method implemented by cloning

4. Notes

Note that the object created by the cloning method is a new object, they have a new address in memory , usually resulting object cloning to modify the prototype object will not have any impact, each clone objects are to each other independent. It can be modified in different ways to obtain a set of similar but not identical objects

5. The structure of FIG. & Role

  • Prototype (abstract class prototype): It is the interface declaration cloning method, all of the specific public prototype parent class, an abstract class may be an interface, it can even be embodied class.
  • ConcretePrototype (particularly class prototype): implements cloning methods declared in the abstract class prototype, return to their cloning a clone in the process.
  • Client (client category): Let a prototype object clone itself to create a new object, only need to directly instantiate or create a prototype object through the factory method, etc. in the customer class, then you can get by calling the object's cloning method a plurality of the same object. Since the client class for abstract class Prototype Prototype programming, the user can select specific category prototypes needed, the system has good scalability, increased or replacement of particular classes easy prototyping

6. Implement


/**

 * @author liuboren

 * @Title: 原形接口类

 * @Description:

 * @date 2019/7/17 13:41

 */

public interface Prototype {

    void setAttr(String attr);



    String getAttr();



    Prototype clone();

}



/**

 * @author liuboren

 * @Title: 原形类的实现类

 * @Description:

 * @date 2019/7/17 13:43

 */

public class ConcretePrototype implements Prototype {



    private String attr;



    @Override

    public String getAttr() {

        return attr;

    }



    @Override

    public void setAttr(String attr) {

        this.attr = attr;

    }



    @Override

    public Prototype clone() {

        Prototype prototype = new ConcretePrototype();

        prototype.setAttr(this.attr);

        return prototype;

    }

}

/**

 * @author liuboren

 * @Title: 客户端类

 * @Description:

 * @date 2019/7/17 13:48

 */

public class Client {



    public static void main(String[] args) {

        Prototype prototype = new ConcretePrototype();

        prototype.setAttr("Prototype");

        Prototype prototypeClone = prototype.clone();

        System.out.println(prototype == prototypeClone);



    }

}

This method can be implemented as a generic prototype model, which is independent of programming language features, any object-oriented language can be used to achieve this form of the prototype clone

6.1 Java realization

Object class provides a clone () method, a Java object can be a copy. Clone Object can be provided directly in Java () method to achieve the object of cloning, Java language is very simple prototype model to achieve

Note that enables cloning Java class must implement an interface to identify the Cloneable , expressed support for the Java class is copied. If a class does not implement this interface, but calls clone () method, Java compiler will throw a CloneNotSupportedException exception.




/**

 * @author liuboren

 * @Title: 原形类的实现类

 * @Description:

 * @date 2019/7/17 13:43

 */

public class ConcretePrototype implements Prototype,Cloneable {



    private String attr;



    @Override

    public String getAttr() {

        return attr;

    }



    @Override

    public void setAttr(String attr) {

        this.attr = attr;

    }



    @Override

    public Prototype clone() {

        Prototype prototype = null;

        try {

             prototype = (Prototype) super.clone();

        } catch (CloneNotSupportedException e) {

            e.printStackTrace();

        }

        return prototype;

    }

}

clone method 6.2 Java language satisfies the following conditions

(1) any object x, x.clone have () = x, i.e. the prototype clone objects are not the same object!;

(2) any object x, has x.clone () getClass () == x.getClass (), i.e. clone with the same type of prototype object.;

(3) If the object x equals () method is defined properly, then x.clone (). Equals (x) should be established.

Step method using the clone 6.3

(1) covering the derived class's base class clone () method, and a statement is public;

(2) in the derived class clone () method is called to super.clone ();

(3) to be achieved by the derived class Cloneable interface

## 7. shallow clone and a deep clone

Shallow clone (shallowClone) and a deep clone (DeepClone). In the Java language, into the data type value type (basic data types) and reference types, including value type int, double, byte, boolean, char and other simple data types, including complex type reference type class, an interface, an array like.

The main difference between deep and shallow clone clone that supports copy member variables of a reference type , both will be described in detail below

7.1 shallow clone

在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。

简单来说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制

在Java语言中,通过覆盖Object类的clone()方法可以实现浅克隆

7.1.1 浅克隆实战

有一个报表类Statement和附件类Attachment,它们的关系如结构图:




/**

 * @author liuboren

 * @Title: 附件类

 * @Description:

 * @date 2019/7/17 14:39

 */

public class Attachment {

    private String name;

    private String content;





    public String getName() {

        return name;

    }



    public void setName(String name) {

        this.name = name;

    }

}





/**

 * @author liuboren

 * @Title: 报表类

 * @Description:

 * @date 2019/7/17 14:38

 */

public class Statement implements Cloneable {

    private String name;

    private Date date;

    private Attachment attachment;



    public String getName() {

        return name;

    }



    public void setName(String name) {

        this.name = name;

    }



    public Date getDate() {

        return date;

    }



    public void setDate(Date date) {

        this.date = date;

    }



    public Attachment getAttachment() {

        return attachment;

    }



    public void setAttachment(Attachment attachment) {

        this.attachment = attachment;

    }



    @Override

    public Statement clone(){

        Statement clone = null;

        try {

            clone = (Statement) super.clone();

        } catch (CloneNotSupportedException e) {

            e.printStackTrace();

        }



        return clone;

    }

}


==方法比较克隆后的两个附件




/**

 * @author liuboren

 * @Title: 客户端

 * @Description:

 * @date 2019/7/17 14:58

 */

public class Client {

    public static void main(String[] args) {

        Statement statement = new Statement();

        statement.setAttachment(new Attachment());

        Statement statementClone = statement.clone();

        System.out.println(statement == statementClone);

        System.out.println(statement.getAttachment() == statementClone.getAttachment());

    }

}


输出:

报表是否相同? false

附件是否相同? true

由于使用的是浅克隆技术,因此报表对象复制成功,通过“==”比较原型对象和克隆对象的内存地址时输出false;但是比较附件对象的内存地址时输出true,说明它们在内存中是同一个对象

7.2 深克隆

在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象

简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制

在Java语言中,如果需要实现深克隆,可以通过序列化(Serialization)等方式来实现。

序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。

通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来,可以实现深克隆.

需要注意的是能够实现序列化的对象其类必须实现Serializable接口,否则无法实现序列化操作。

7.2.1 深克隆实战




/**

 * @author liuboren

 * @Title: 报表类

 * @Description:

 * @date 2019/7/17 14:38

 */

public class Statement implements Serializable {

    private String name;

    private Date date;

    private Attachment attachment;



    public String getName() {

        return name;

    }



    public void setName(String name) {

        this.name = name;

    }



    public Date getDate() {

        return date;

    }



    public void setDate(Date date) {

        this.date = date;

    }



    public Attachment getAttachment() {

        return attachment;

    }



    public void setAttachment(Attachment attachment) {

        this.attachment = attachment;

    }



    /*深克隆*/

    public Statement deepClone() throws IOException, ClassNotFoundException {

        //将对象写入流

        ByteArrayOutputStream bao = new ByteArrayOutputStream();

        ObjectOutputStream oos = new ObjectOutputStream(bao);

        oos.writeObject(this);



        //将对象从流中取出

        ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());

        ObjectInputStream ois = new ObjectInputStream(bis);



        return (Statement) ois.readObject();

    }

}





/**

 * @author liuboren

 * @Title: 附件类

 * @Description:

 * @date 2019/7/17 14:39

 */

public class Attachment implements Serializable {

    private String name;

    private String content;





    public String getName() {

        return name;

    }



    public void setName(String name) {

        this.name = name;

    }



    public String getContent() {

        return content;

    }



    public void setContent(String content) {

        this.content = content;

    }

}



/**

 * @author liuboren

 * @Title: 客户端

 * @Description:

 * @date 2019/7/17 14:58

 */

public class Client {

    public static void main(String[] args) throws IOException, ClassNotFoundException {

        Statement statement = new Statement();

        statement.setAttachment(new Attachment());

        Statement statementClone = statement.deepClone();

        System.out.println("报表是否相同? "+(statement == statementClone));
![](https://img2018.cnblogs.com/blog/1316204/201907/1316204-20190722122905386-316032736.png)

        System.out.println("附件是否相同? " + (statement.getAttachment() == statementClone.getAttachment()));

    }

}

从输出结果可以看出,由于使用了深克隆技术,附件对象也得以复制,因此用“==”比较原型对象的附件和克隆对象的附件时输出结果均为false。深克隆技术实现了原型对象和克隆对象的完全独立,对任意克隆对象的修改都不会给其他对象产生影响,是一种更为理想的克隆实现方式

8. 原形管理器

原型管理器(Prototype Manager)是将多个原型对象存储在一个集合中供客户端使用,它是一个专门负责克隆对象的工厂,其中定义了一个集合用于存储原型对象,如果需要某个原型对象的一个克隆,可以通过复制集合中对应的原型对象来获得。在原型管理器中针对抽象原型类进行编程,以便扩展

9.总结

9.1 优点

(1) 当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,通过复制一个已有实例可以提高新实例的创建效率。

(2) 扩展性较好,由于在原型模式中提供了抽象原型类,在客户端可以针对抽象原型类进行编程,而将具体原型类写在配置文件中,增加或减少产品类对原有系统都没有任何影响。

(3) 原型模式提供了简化的创建结构,工厂方法模式常常需要有一个与产品类等级结构相同的工厂等级结构,而原型模式就不需要这样,原型模式中产品的复制是通过封装在原型类中的克隆方法实现的,无须专门的工厂类来创建产品。

(4) 可以使用深克隆的方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用(如恢复到某一历史状态),可辅助实现撤销操作。

9.2 缺点

(1) 需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时,需要修改源代码,违背了“开闭原则”。

(2) 在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重的嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来可能会比较麻烦。

9.3 适用场景

(1) 创建新对象成本较大(如初始化需要占用较长的时间,占用太多的CPU资源或网络资源),新的对象可以通过原型模式对已有对象进行复制来获得,如果是相似对象,则可以对其成员变量稍作修改。

(2) 如果系统要保存对象的状态,而对象的状态变化很小,或者对象本身占用内存较少时,可以使用原型模式配合备忘录模式来实现。

(3) 需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方便。

Guess you like

Origin www.cnblogs.com/xisuo/p/11225703.html