Java Design Patterns--Prototype Pattern

1 Prototype Pattern

Purpose: Create a new object by "copying and pasting" at runtime;
Implementation: Create a prototype object, and then copy the prototype object to create more objects of the same type through the clone implementation method commonly used in the Java language.

2 Implementation

Code scene: After the success of the October Revolution, the powerful Soviet Union helped the surrounding countries still in war to find a direction to struggle. Many political parties followed the Soviet model to carry out revolutions and formulate national development policies.

2.1 Code Implementation

The Communist Idea Interface: It Needs Aspirants to Realize

public interface Communism extends Cloneable {
    // 可以被模仿 从未被超越
    public Communism getClone();
    // 走中国特色社会主义道路
    public Communism deepClone();
    // 你的追求
    public String getBelief();
    // 报上你的情况 为了演示 浅克隆 深克隆
    public NationalSituation getNationalSituation();
}

Big Brother Soviet Union: Serializable is implemented in order to achieve deep cloning

public class Soviet implements Communism ,Serializable{
    private static final long serialVersionUID = 5344691963719733036L;
    private NationalSituation ns = new NationalSituation();
    private String belief;
    public Soviet(String belief, String nationalArea, String nationalPopulation, String technicalLevel) {
        ns.setNationalArea(nationalArea);
        ns.setNationalPopulation(nationalPopulation);
        ns.setTechnicalLevel(technicalLevel);
        this.belief = belief;
    }
    @Override
    public Communism getClone() {
        Communism c = null;
        try {
            c = (Communism) super.clone();
        } catch (CloneNotSupportedException e) {
             System.out.println("不支持复制!");
             return null;
        }
        return c;
    }
    @Override
    public String getBelief() {
        System.out.println("我是国土面积:[" + ns.getNationalArea() 
            + "]"+ ",人口:[" + ns.getNationalPopulation() 
            + "],我的信仰是:实现[" + belief+"]");
        return belief;
    }

    @Override
    public NationalSituation getNationalSituation() {
        return ns;
    }
    // 使用序列化技术实现深克隆
    public Communism deepClone() {
        // 将对象写入流中
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        ObjectOutputStream oos;
        ByteArrayInputStream bis;
        try {
            oos = new ObjectOutputStream(bao);
            oos.writeObject(this);
            // 将对象从流中取出
            bis = new ByteArrayInputStream(bao.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (Communism) ois.readObject();
        } catch (ClassNotFoundException | IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

Private attributes: national conditions, Serializable is implemented in order to achieve deep cloning

public class NationalSituation implements Serializable{
    private static final long serialVersionUID = 1864667007956857078L;
    // 人口
    private String NationalPopulation;
    // 国土面积
    private String NationalArea;
    // 技术水平
    private String TechnicalLevel;
    public String getNationalPopulation() {
        return NationalPopulation;
    }
    public void setNationalPopulation(String nationalPopulation) {
        NationalPopulation = nationalPopulation;
    }
    public String getNationalArea() {
        return NationalArea;
    }
    public void setNationalArea(String nationalArea) {
        NationalArea = nationalArea;
    }
    public String getTechnicalLevel() {
        return TechnicalLevel;
    }
    public void setTechnicalLevel(String technicalLevel) {
        TechnicalLevel = technicalLevel;
    }

}

2.2 Involving roles

The following roles are included in the prototype pattern structure diagram:
Prototype (abstract prototype class): It is the interface that declares the clone method, and is the common parent class of all concrete prototype classes. It can be an abstract class or an interface, or even an abstract class. Concrete implementation class.

ConcretePrototype (concrete prototype class): It implements the clone method declared in the abstract prototype class, and returns a clone object of itself in the clone method.

Client (client class): Let a prototype object clone itself to create a new object. In the client class, you only need to directly instantiate or create a prototype object through a factory method, and then call the clone method of the object to get multiple identical objects. Since the client class is programmed for the abstract prototype class Prototype, the user can select the concrete prototype class according to the needs, the system has good scalability, and it is very convenient to add or replace the concrete prototype class.

2.3 call

public class Client {

    public static void main(String[] args) {
        // 苏联
        Communism soviet = new Soviet("共产主义", "很大很大", "2亿", "牛逼");
        // 中国
        Communism china = soviet.deepClone();
        // 朝鲜
        Communism Korea = soviet.getClone();
        // 越南
        Communism vietnam = soviet.getClone();

        System.out.println("-------------苏联--------------");
        String sovietBelief = soviet.getBelief();
        System.out.println("-------------中国--------------");
        String chinaBelief = china.getBelief();
        System.out.println("-------------朝鲜--------------");
        String koreaBelief = Korea.getBelief();
        System.out.println("-------------浅克隆--------------");
        // 查看是否指向一个地址
        if (soviet == Korea) {
            System.out.println("soviet == Korea");
        } else {
            System.out.println("soviet != Korea");
        }
        // 查看内部属性是否指向一个地址
        if (sovietBelief == koreaBelief) {
            System.out.println("sovietBelief == koreaBelief");
        } else {
            System.out.println("sovietBelief != koreaBelief");
        }

        // 查看内部属性是否指向一个地址
        if (soviet.getNationalSituation() == Korea.getNationalSituation()) {
            System.out.println("soviet.getNationalSituation == Korea.getNationalSituation");
        } else {
            System.out.println("soviet.getNationalSituation != Korea.getNationalSituation");
        }
        System.out.println("-------------深克隆--------------");
        System.out.println("-及时修正路线:农村包围城市,中国特色社会主义-");
        // 查看是否指向一个地址
        if (soviet == china) {
            System.out.println("soviet == china");
        } else {
            System.out.println("soviet != china");
        }
        // 查看内部属性是否指向一个地址
        if (sovietBelief == chinaBelief) {
            System.out.println("sovietBelief == chinaBelief");
        } else {
            System.out.println("sovietBelief != chinaBelief");
        }

        // 查看内部属性是否指向一个地址
        if (soviet.getNationalSituation() == china.getNationalSituation()) {
            System.out.println("soviet.getNationalSituation == china.getNationalSituation");
        } else {
            System.out.println("soviet.getNationalSituation != china.getNationalSituation");
        }

    }

}

result:

-------------苏联--------------
我是国土面积:[很大很大],人口:[2亿],我的信仰是:实现[共产主义]
-------------中国--------------
我是国土面积:[很大很大],人口:[2亿],我的信仰是:实现[共产主义]
-------------朝鲜--------------
我是国土面积:[很大很大],人口:[2亿],我的信仰是:实现[共产主义]
-------------浅克隆--------------
soviet != Korea
sovietBelief == koreaBelief
soviet.getNationalSituation == Korea.getNationalSituation
-------------深克隆--------------
-及时修正路线:农村包围城市,中国特色社会主义-
soviet != china
sovietBelief != chinaBelief
soviet.getNationalSituation != china.getNationalSituation

North Korea performed shallow cloning, and China performed deep cloning.

3 Shallow Clone & Deep Clone

3.1 Shallow clone

In shallow cloning, if the member variable of the prototype object is a value type, a copy will be made to the cloned object; if the member variable of the prototype object is a reference type, a copy of the address of the reference object will be copied to the cloned object, that is, the prototype The member variables of the object and the cloned object point to the same memory address. Simply put, in shallow cloning, when the object is copied, only itself and the member variables of the value type contained in it are copied, while the member objects of the reference type are not copied, as shown in the figure:
write picture description here
In the Java language, by overwriting The clone() method of the Object class enables shallow cloning.

In general, the clone() method in the Java language satisfies:
(1) For any object x, there is x.clone() != x, that is, the cloned object and the prototype object are not the same object;
(2) For any object x, all have x.clone().getClass() == x.getClass(), that is, the cloned object has the same type as the prototype object;
(3) If the equals() method of the object x is properly defined, then x.clone( ).equals(x) should hold.

In order to obtain a copy of the object, we can directly use the clone() method of the Object class. The specific steps are as follows:
(1) Override the clone() method of the base class in the derived class and declare it as public;
(2) In the derived class In the clone() method of the class, call super.clone();
(3) The derived class needs to implement the Cloneable interface.
At this point, the Object class is equivalent to the abstract prototype class, and all the classes that implement the Cloneable interface are equivalent to the concrete prototype class.


3.2 Deep clone

In deep cloning, no matter whether the member variable of the prototype object is a value type or a reference type, a copy will be made to the cloned object, and a copy of all the reference objects of the prototype object will also be copied to the cloned object. In simple terms, in deep cloning, in addition to the object itself being copied, all member variables contained in the object will also be copied, as shown in the figure:
write picture description here

In the Java language, if deep cloning needs to be implemented, it can be implemented by means such as serialization. Serialization is the process of writing an object to a stream. The object written to the stream is a copy of the original object, and the original object still exists in memory. The copy realized by serialization can not only copy the object itself, but also copy the member objects it refers to. Therefore, by serializing the object to a stream, and then reading it from the stream, deep cloning can be achieved. It should be noted that the class of the object that can implement serialization must implement the Serializable interface, otherwise the serialization operation cannot be implemented.

Code address: click to jump

References:
[1] Graphical Design Patterns/(Japanese) Hiroshi Yuki; translated by Yang Wenxuan. – Beijing: People’s Posts and Telecommunications Press, 2017.1.
[ 2 ] Wikipedia Design
Patterns [ 3 ] Geek Academy WIKI – Design Patterns .
[ 4 ] Rookie Tutorial – Design Patterns .

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325159836&siteId=291194637