Design pattern (14) - prototype patterns (the Prototype)

Concept definition

Examples of a prototype to be created to specify the type of the object, and to create new objects by copying this prototype. Prototype prototype object model allows a clone (copy) a plurality of objects identical thereto, without having to know any details of how to create.

Scenarios

  • The creation of objects to create more complex and require frequent
  • It is desirable to generate a new instance according to a conventional example, for example:
    • When a wide range of objects can not be integrated into a class
    • When it is difficult to specify the class name generated by the instance of
    • Examples of the generated frame when the desired decoupling

In practical applications, Prototype models rarely occur alone. Often mixed with other modes.

Prototype implementation

All classes inherit from Java java.lang.Object, and Object class provides clone () method to clone objects. Accordingly, the Java class that implements the interface and rewrites Cloneable clone () method, can be realized Prototype pattern .

Prototype pattern example code as follows:

// 原型类(也可定义为interface Prototype extends Cloneable)
abstract class Prototype implements Cloneable {
    private String name;
    public void setName(String name) {this.name = name;}
    public String getName() {return this.name;}

    public abstract void doSomething();

    @Override
    public Object clone() { // clone()方法用public修饰
        Object object = null;
        try {
            object = super.clone(); // 调用父类clone()方法
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return object;
    }
}

// 具体实现类(继承自Prototype类自动具有克隆功能)
class ConcretePrototype extends Prototype{
    public ConcretePrototype() { setName("ConcretePrototype"); }

    @Override
    public void doSomething() { System.out.println("I'll clone myself!"); }
}

public class PrototypeDemo {
    public static void main(String[] args) {
        ConcretePrototype cp = new ConcretePrototype();
        cp.doSomething();

        for(int i=0; i< 5; i++){
            ConcretePrototype cloned = (ConcretePrototype)cp.clone();
            System.out.println("I'm cloned by " + cloned.getName());
        }
    }
}

After performing the following output:

I'll clone myself!
I'm cloned by ConcretePrototype
I'm cloned by ConcretePrototype
I'm cloned by ConcretePrototype
I'm cloned by ConcretePrototype
I'm cloned by ConcretePrototype

The advantages and disadvantages mode

Prototype pattern following advantages:

  • Depending on the client requirements for dynamic objects to create run-time client does not need to know the details of creating objects, easy to maintain and expand code.
  • When creating an object to create more complex or repeated a large number of similar objects, the object is to create simplified, and the performance (will automatically call all the new Constructor chain, but does not call any clone class constructor method) higher than the new objects directly .
  • Prototype pattern similar to the factory mode, but there is no hierarchical relationship abstract factory model plants and plant-specific code structure clearer and simpler.

Shortcomings are as follows:

  • Require () must be modified for each class implements Cloneable interface and override the clone method when, by altering the existing class of its source, contrary to the "principle of opening and closing."
  • Singleton and factory model, Prototype models are in conflict, try not to mix.
  • When implementing a deep copy (deep clone) need to write complicated code.

Precautions

clone () method of copying only the basic data types of objects, without copying the array, the container object, the object reference and the like. To achieve deep copy, you must Prototype array mode, the container object, reference object like a separate copy .
Other objects, for example, when a deep copy of the object, the object must implement Cloneable interface and override clone () method, and the object within the reference clone () method is also a clone. Similarly, the referenced object also do the same process.
Note, Boolean, Byte, Character, Class , Double, Float, Integer, Long, Short, String , and most of Exception subclasses are immutable class, it is not necessary to implement a deep copy the object. In addition, most of the Java container classes have been achieved cloning function.

In contrast, clone () method is more suitable for an array of deep copy. But note the following two points:

(1) basic types of one-dimensional array by such (int[])data.clone()forms of cloning, the basic type of "two-dimensional array" (actually, such as a type int [] is a one-dimensional array) required by Wei Kelong. E.g:

public static int[][] twoDimensionArrayClone (int[][] tdArray){
    int[][] copy = tdArray.clone();
    for (int i = 0; i < tdArray.length; i++) {
        copy[i] = tdArray[i].clone();
    }
    return copy;
}

(2) When the array elements to ordinary Java objects, but also the clone cloned array contained in the array. The following examples show in detail the different ways a shallow vs. deep copy of the array of objects:

class Person implements Cloneable {
    public String name;
    public Person(String name) {this.name = name;}

    @Override
    public Object clone() {
        Object object = null;
        try {
            object = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return object;
    }
}

public class ArrayPrototype {
    public static void main(String[] args) {
		Person[] origin = new Person[] { new Person("Mike"), new Person("Jack"), new Person("Jason") };
		Person[] copyOf = Arrays.copyOf(origin, origin.length);
		// 浅拷贝(内部调用System.arraycopy,返回新数组)
		Person[] arrayCopy = new Person[origin.length];
		// 浅拷贝(可拷贝部分数组)
		System.arraycopy(origin, 0, arrayCopy, 0, origin.length);
		Person[] clonedCopy = origin.clone();
		// 浅拷贝
		System.out.println("origin=copyOf=arrayCopy=clonedCopy="
				+ (origin[0] == copyOf[0] && copyOf[1] == arrayCopy[1] && arrayCopy[2] == clonedCopy[2]));
		clonedCopy[0].name = "Lily";
		System.out.println("Shallow Person[0]: " + origin[0].name + " -> " + clonedCopy[0].name);

		Person[] deepCopy = new Person[origin.length];
		// 深拷贝
		for (int i = 0; i < origin.length; i++) {
			deepCopy[i] = (Person) origin[i].clone();
		}
		deepCopy[1].name = "Lily";
		System.out.println("Deep Person[1]: " + origin[1].name + " -> " + clonedCopy[1].name);
		Person[] deepCopy2 = Arrays.stream(origin).map(Person::clone).toArray(Person[]::new);
		// 深拷贝
		deepCopy2[2].name = "Lucy";
		System.out.println("Deep Person[2]: " + origin[2].name + " -> " + deepCopy2[2].name);
	}
}

Industry practice

  • Action Objects (Struts2)
  • bean instance (Spring) prototype created
Published 295 original articles · won praise 37 · views 30000 +

Guess you like

Origin blog.csdn.net/tianshan2010/article/details/104722260