Hello everyone, I am Wolf King, a programmer who loves playing ball

This is part 5 of the Design Patterns series, and in this part, we’ll take a look at prototyping patterns


1, an overview of the

The prototype pattern is a creative design pattern that allows you to copy existing objects, even complex objects, without having to make your code dependent on the class to which they belong.

The prototype pattern delegates the cloning process to the actual object being cloned. The pattern declares a common interface for all objects that support cloning, which allows you to clone objects without coupling your code to the class that the object belongs to. Typically, such an interface contains only one clone method.

2. Applicable scenarios

1) You need to copy objects without making your code independent of the class they belong to.

2) Reduce unnecessary object initialization when only objects need to be acquired, and just call the appropriate object cloning method.

3, the instance,

Java’s Cloneable (clone) interface is an immediate prototype pattern. Any class can implement clonable properties by implementing this interface.

There is a distinction between shallow copy and deep copy. The following two words are analyzed in combination with the code.

Clone () {Engine (); Cloneable ();

@Data
public class Car implements Cloneable{

    private int seats;

    private Engine engine;

    public Car(int seats, Engine engine) {
        this.seats = seats;
        this.engine = engine;
    }

    public void detail(a) {
        System.out.println("the seats is :" + seats);
        System.out.println("the engine is :" + engine);
    }

    @Override
    public Car clone(a) throws CloneNotSupportedException{
        return (Car) super.clone(); }}Copy the code
@Data
public class Engine {

    /** ** displacement */
    private final double volume;
    /** ** mileage */
    private double mileage;

    public Engine(double volume, double mileage) {
        this.volume = volume;
        this.mileage = mileage; }}Copy the code

The test class:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class TestDemo {

    @Test
    public void test(a) throws CloneNotSupportedException {
        Car car = new Car(2.new Engine(3.0.0));
        Car car1 = car.clone();
        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- printing car -- -- -- -- -- -- -- -- -- -- -- --");
        car.detail();
        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- print car1 -- -- -- -- -- -- -- -- -- -- -- --");
        car1.detail();
        System.out.println("------------ Modifies car seats to print car------------");
        car.setSeats(4);
        car.detail();
        System.out.println("------------ Modify car seats print car1------------");
        car1.detail();
        System.out.println("------------ modify the Engine of car to print car------------");
        car.getEngine().setMileage(10000);
        car.detail();
        System.out.println("------------ modify the Engine of car to print car1------------"); car1.detail(); }}Copy the code

Results:

------------ Print car------------ the seats is:2
the engine is :Engine(volume=3.0, mileage=0.0) ------------ print car1------------ the seats is:2
the engine is :Engine(volume=3.0, mileage=0.0) -- -- -- -- -- -- -- -- -- -- -- -- modified car seats to print the car -- -- -- -- -- -- -- -- -- -- -- -- the seats is:4
the engine is :Engine(volume=3.0, mileage=0.0) -- -- -- -- -- -- -- -- -- -- -- -- modified car seats print car1 -- -- -- -- -- -- -- -- -- -- -- -- the seats is:2
the engine is :Engine(volume=3.0, mileage=0.0) -- -- -- -- -- -- -- -- -- -- -- -- change the car's Engine to print the car -- -- -- -- -- -- -- -- -- -- -- -- the seats is:4
the engine is :Engine(volume=3.0, mileage=10000.0) -- -- -- -- -- -- -- -- -- -- -- -- change the car's Engine to print car1 -- -- -- -- -- -- -- -- -- -- -- -- the seats is:2
the engine is :Engine(volume=3.0, mileage=10000.0)
Copy the code

4, analysis,

Analyze the above results:

Car1 is obtained through the clone() method of CAR, and its internal attributes are the same.

When modifying seats of CAR, it is found that car changes but CAR1 value does not.

When the Engine property object of car is modified, car changes, and so does CAR1.

The reason why Engine in CAR1 was also modified: value references and address references.

Here involves the content of the Java memory model, here is a simple explanation to explain the problem:

Each Java thread has a private Java virtual machine stack that is created at the same time as the thread. Within the virtual machine stack, each method generates a stack frame. Each stack frame represents one method call after another, the process from execution of a method to completion of execution, and the process from stack frame to stack frame.

The stack frame contains a local variable table, and the local variable table can store two types of values, including the original type and the reference type. An object within an object is a reference stored in the local variable table of the stack frame that points to a pointer to an object in the heap, and there is only one of the same objects in the heap.

When two objects refer to an object at the same time, they are actually referring to the same object in the heap, and when the value of this object is modified, the values in all objects that refer to this object are changed.

How to solve the above problems?

The above method is called shallow copy.

Deep copy: Engine implements the Cloneable interface, overwriting the Clone method, and Car calls Engine’s clone method.

@Data
public class Engine implements Cloneable{

    /** ** displacement */
    private final double volume;
    /** ** mileage */
    private double mileage;

    public Engine(double volume, double mileage) {
        this.volume = volume;
        this.mileage = mileage;
    }

    @Override
    public Engine clone(a) throws CloneNotSupportedException {
        Engine clone = (Engine) super.clone();
        returnclone; }}Copy the code
public class Car implements Cloneable{

    private int seats;

    private Engine engine;

    public Car(int seats, Engine engine) {
        this.seats = seats;
        this.engine = engine;
    }

    public void detail(a) {
        System.out.println("the seats is :" + seats);
        System.out.println("the engine is :" + engine);
    }

    @Override
    public Car clone(a) throws CloneNotSupportedException{
        Car car = (Car) super.clone();
        car.engine = engine.clone();
        returncar; }}Copy the code

Execution Result:

------------ Print car------------ the seats is:2
the engine is :Engine(volume=3.0, mileage=0.0) ------------ print car1------------ the seats is:2
the engine is :Engine(volume=3.0, mileage=0.0) -- -- -- -- -- -- -- -- -- -- -- -- modified car seats to print the car -- -- -- -- -- -- -- -- -- -- -- -- the seats is:4
the engine is :Engine(volume=3.0, mileage=0.0) -- -- -- -- -- -- -- -- -- -- -- -- modified car seats print car1 -- -- -- -- -- -- -- -- -- -- -- -- the seats is:2
the engine is :Engine(volume=3.0, mileage=0.0) -- -- -- -- -- -- -- -- -- -- -- -- change the car's Engine to print the car -- -- -- -- -- -- -- -- -- -- -- -- the seats is:4
the engine is :Engine(volume=3.0, mileage=10000.0) -- -- -- -- -- -- -- -- -- -- -- -- change the car's Engine to print car1 -- -- -- -- -- -- -- -- -- -- -- -- the seats is:2
the engine is :Engine(volume=3.0, mileage=0.0)
Copy the code

In the above results, only the CAR engine was modified to achieve the deep copy effect.

5, summary

Finally, summarize the pros and cons of using the prototype pattern in the example above:

Advantages:

1) Clone objects without concern for their associated classes, such as Engine in Car.

2) Reduce repeated initialization code.

3) For complex objects, it is relatively easy to generate.

4) You can reduce inherited relationships by copying objects.

Disadvantages:

Be aware of the problem of deep and shallow copies, which are more complex to implement when multiple references are involved.

VX search: Wolf king programming white whoring a lot of learning resources!