Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Detailed explanation of prototype pattern in Java Design pattern

2025-02-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly introduces "detailed interpretation of prototype patterns in Java design patterns". In daily operation, I believe that many people have doubts about the detailed interpretation of prototype patterns in Java design patterns. The editor consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful to answer the doubts of "detailed interpretation of prototype patterns in Java design patterns". Next, please follow the editor to study!

Catalogue

Introduction

Role

Clone () method provided by Java language

Code demo-cloned sheep

Conclusion

Deep and shallow copy

Discussion on deep and shallow copy

The first way to achieve deep cloning is to clone reference objects manually.

The first way to achieve deep cloning: serialization

The destruction of prototype pattern to singleton pattern

Advantages and disadvantages

Applicable scenario

Application scenario of prototype pattern in Spring

Introduction

Prototype pattern (Prototype Pattern): use prototype instances to specify the types of objects to be created, and create new objects by copying these prototypes. Prototype pattern is a kind of object creation pattern.

The prototype pattern works simply by passing a prototype object to the object to be created, which implements the creation process by requesting the prototype object to copy itself.

The prototype pattern is an "alternative" creative pattern. The factory for creating cloned objects is the prototype class itself, and the factory method is implemented by the cloning method.

It should be noted that the objects created by the cloning method are brand new objects, they have a new address in memory, and usually modifications to the cloned objects will not have any effect on the prototype objects. each cloned object is independent of each other. A series of similar but not identical objects can be obtained by modifying them in different ways.

Role

Prototype (Abstract prototype Class): it is the interface that declares clone methods and is the common parent of all concrete prototype classes. It can be an abstract class, an interface, or even a concrete implementation class.

ConcretePrototype (concrete prototype class): it implements the clone method declared in the abstract prototype class and returns one of its own clone objects 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 instantiate it directly or create a prototype object through the factory method, and then you can get multiple identical objects by calling the cloning method of the object. Because the client class is programmed for the abstract prototype class Prototype, users can choose the concrete prototype class according to their needs. The system has good expansibility, and it is convenient to add or replace the concrete prototype class.

The core of the prototype pattern is how to implement the cloning method.

Clone () method provided by Java language

Anyone who has learned the Java language knows that all Java classes inherit from java.lang.Object. In fact, the Object class provides a clone () method that makes a copy of a Java object. Therefore, you can directly use the clone () method provided by Object to clone objects in Java, and the implementation of the prototype pattern in Java is very simple.

It is important to note that a Java class that can be cloned must implement an identification interface Cloneable, indicating that the Java class supports replication. If a class does not implement this interface but calls the clone () method, the Java compiler throws a CloneNotSupportedException exception.

Code demo-cloned sheep

Specific prototype class:

/ / implement the Cloneable interface @ Datapublic class Sheep implements Cloneable {private String name; private Integer age; / / override Object's clone method @ Override protected Object clone () throws CloneNotSupportedException {Sheep sheep=null; sheep= (Sheep) super.clone (); return sheep;}}

The client creates and clones the prototype object:

/ / create prototype object Sheep sheep=new Sheep (); sheep.setAge (3); sheep.setName ("Sean"); / / Clone Sheep sheep1= sheep.clone (); Sheep sheep2=sheep.clone (); System.out.println (sheep1); System.out.println (sheep2); System.out.println (sheep1==sheep2)

Conclusion

The cloned objects have different memory addresses, indicating that they are not the same object. The cloned objects can be cloned only by calling super.clone ().

Take a look at the Object#clone method

Protected native Object clone () throws CloneNotSupportedException

This is a native keyword modification method

In general, the clone () method in the Java language satisfies:

For any object x, there is x.clone ()! = x, that is, the cloned object and the prototype object are not the same object.

For any object x, there is x.clone (). GetClass () = = x.getClass (), that is, the cloned object is of the same type as the prototype object

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

To get a copy of the object, we can directly use the clone () method of the Object class, as follows:

Override the clone () method of the base class in the derived class and declare it as public

In the clone () method of the derived class, call super.clone ()

Derived classes need to implement the Cloneable interface.

At this point, the Object class is equivalent to the abstract prototype class, and all classes that implement the Cloneable interface are equivalent to the concrete prototype class.

Deep and shallow copy

Pig class:

@ Data@AllArgsConstructor@NoArgsConstructorpublic class Pig {String name; Integer age;}

Sheep class:

/ / implement the Cloneable interface @ Datapublic class Sheep implements Cloneable {private String name; private Integer age; private Pig pig; / / override Object's clone method @ Override protected Sheep clone () throws CloneNotSupportedException {Sheep sheep=null; sheep= (Sheep) super.clone (); return sheep;}}

The client is cloned:

Public class test {@ Test public void test () throws CloneNotSupportedException {/ / create prototype object Sheep sheep=new Sheep (); sheep.setAge (3); sheep.setName ("Shawn"); sheep.setPig (new Pig ("big bluff", 3)); / / Clone Sheep sheep1 = sheep.clone (); Sheep sheep2=sheep.clone (); System.out.println (sheep1) System.out.println (sheep2); System.out.println (sheep1==sheep2); System.out.println ("= ="); System.out.println (sheep1.getPig () = = sheep2.getPig ());}}

Here, the cloning of the reference type Pig in the Sheep class is only a simple address copy, that is, a shallow copy operation.

Discussion on deep and shallow copy

Shallow Clone:

In shallow cloning, if the member variable of the prototype object is a value type, a copy is made to the cloned object; if the member variable of the prototype object is a reference type, a copy of the address of the referenced object is made to the cloned object, that is, the member variables of the prototype object and the cloned object point to the same memory address.

To put it simply, in a shallow clone, when an object is copied, only it and the member variables of the value types it contains are copied, while the member objects of the reference type are not copied.

In the Java language, shallow cloning can be achieved by overriding the clone () method of the Object class

Deep cloning:

In deep cloning, a copy is made to the cloned object regardless of whether the member variable of the prototype object is a value type or a reference type, and deep cloning copies all reference objects of the prototype object to the cloned object as well.

To put it simply, in a deep clone, in addition to the object itself, all member variables contained in the object are copied.

In the Java language, if you need to implement deep cloning, you can do it through Serialization and so on. It should be noted that the class of an object that can be serialized must implement the Serializable interface, otherwise the serialization operation cannot be implemented.

The first way to achieve deep cloning is to clone reference objects manually.

The Pig class first needs to be cloned and overridden the clone method:

@ Data@AllArgsConstructor@NoArgsConstructorpublic class Pig implements Cloneable {String name; Integer age; @ Override protected Object clone () throws CloneNotSupportedException {return super.clone ()}}

Sheep class:

/ / implement Cloneable interface @ Datapublic class Sheep implements Cloneable {private String name; private Integer age; private Pig pig; / / override Object's clone method @ Override protected Sheep clone () throws CloneNotSupportedException {Sheep sheep=null; sheep= (Sheep) super.clone (); sheep.pig= (Pig) sheep.pig.clone (); return sheep;}}

The first way to achieve deep cloning: serialization

The premise that objects can be serialized is that the Serializable interface is implemented, where both Sheep and Pig need to implement this interface

Pig class:

@ Data@AllArgsConstructor@NoArgsConstructorpublic class Pig implements Serializable {String name; Integer age;}

Sheep class:

/ / implement the Cloneable interface @ Datapublic class Sheep implements Serializable {private String name; private Integer age; private Pig pig; / / serialize to complete the deep copy of public Sheep deepClone () throws IOException. ClassNotFoundException {/ / first writes the serialized object to ByteArrayOutputStream baot=new ByteArrayOutputStream (); / / the parameter of the ObjectOutputStream constructor is where to write the object stream to ObjectOutputStream oot=new ObjectOutputStream (baot) Oot.writeObject (this); / / read serialized objects from the stream ByteArrayInputStream bait=new ByteArrayInputStream (baot.toByteArray ()); ObjectInputStream oit=new ObjectInputStream (bait); return (Sheep) oit.readObject ();}}

The destruction of prototype pattern to singleton pattern

The single case model of the hungry Han style is as follows:

Public class HungrySingleton implements Serializable, Cloneable {private final static HungrySingleton hungrySingleton; static {hungrySingleton = new HungrySingleton ();} private HungrySingleton () {} public static HungrySingleton getInstance () {return hungrySingleton;} private Object readResolve () {return hungrySingleton;} @ Override protected Object clone () throws CloneNotSupportedException {return super.clone ();}

To get the object using reflection, test as follows

Public class Test {public static void main (String [] args) throws CloneNotSupportedException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {HungrySingleton hungrySingleton = HungrySingleton.getInstance (); Method method = hungrySingleton.getClass (). GetDeclaredMethod ("clone"); method.setAccessible (true); HungrySingleton cloneHungrySingleton = (HungrySingleton) method.invoke (hungrySingleton); System.out.println (hungrySingleton); System.out.println (cloneHungrySingleton);}}

Output

Com.designpattern.HungrySingleton@34c45dca

Com.designpattern.HungrySingleton@52cc8049

As you can see, through the prototype pattern, we destroyed the singleton pattern, and now there are two objects.

To prevent the singleton from being broken, we can either not implement the Cloneable interface, or change the clone method to the following

@ Override protected Object clone () throws CloneNotSupportedException {return getInstance ();} advantages and disadvantages

The main advantages of the prototype pattern are as follows:

When creating a new object instance is complex, using the prototype pattern can simplify the object creation process and improve the efficiency of creating a new instance by copying an existing instance.

Because the abstract prototype class is provided in the prototype pattern, the abstract prototype class can be programmed on the client side, while the concrete prototype class is written in the configuration file, adding or decreasing the product class has no effect on the original system.

The prototype pattern provides a simplified creation structure, and the factory method pattern often requires a factory hierarchy structure that is the same as the product class hierarchy, while the prototype pattern does not. The replication of products in the prototype pattern is achieved through cloning methods encapsulated in the prototype class, and there is no need for a special factory class to create the product.

You can save the state of an object by deep cloning, and use prototype mode to make a copy of the object and save its state so that it can be used when needed (such as restoring to a historical state) to assist in undo operations.

The main disadvantages of the prototype pattern are as follows:

Each class needs to be equipped with a clone method, and the clone method is located inside a class. When modifying an existing class, the source code needs to be modified, which violates the "open-close principle".

When implementing deep cloning, you need to write more complex code, and when there are multiple nested references between objects, in order to achieve deep cloning, the corresponding classes of objects in each layer must support deep cloning, which may be troublesome to implement.

Applicable scenario

It is expensive to create new objects (for example, initialization takes a long time and takes up too much CPU resources or network resources). New objects can be obtained by copying existing objects through prototype mode, and if they are similar objects, their member variables can be slightly modified.

If the system wants to save the state of the object, but the state of the object changes little, or the object itself takes up less memory, you can use the prototype pattern with the memo mode to achieve.

You need to avoid using hierarchical factory classes to create hierarchical objects, and the instance objects of the class have only one or few combined states. getting a new instance by copying a prototype object may be more convenient than using a constructor to create a new instance.

Application scenario of prototype pattern in Spring

In Spring, users can also use the prototype pattern to create new Bean instances, so that each time the new instance is obtained through cloning, and the modification of the new instance does not affect the original instance object.

The prototype pattern here, which is often referred to as the multi-instance pattern in Spring, is also known as the single-instance pattern in Spring, namely Sigleton

At this point, the study of "detailed interpretation of prototype patterns in Java design patterns" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report