Wechat search [Santaizi Aobing] focus on this greedy and lustful programmer.

This article has been included in GitHub github.com/JavaFamily, there are a line of large factory interview complete test sites, information and my series of articles.

preface

In the design patterns series, we’ve written about the factory pattern, the single-column pattern, and the Builder pattern. In the creation pattern, we want to share with you the prototype pattern

Prototyping is a common but often overlooked pattern in our code, so what is it?

The prototype mode is actually a method of cloning objects, which is very common in our coding. For example, beanutils.copyProperties is a shallow copy of objects. So for some special scenarios we still need to clone objects that are already instantiated:

  • Rely on external resources or hardware intensive operations, such as database queries, or scenarios where IO operations exist
  • The condition in which a copy of the same object is obtained in the same state without the need to create a duplicate operation to obtain the state

Take a look at our class diagram:

In the figure above we can see that the prototype pattern is actually quite simple:

  • Clone method can be an interface or a base class. In simple scenarios, we can not use the base class directly to concrete classes.
  • The second is the concreteprototype class, which implements or extends the clone method. When we use an object method in a concreteprototype class, it returns an abstract prototype object of the base class

For the above theoretical knowledge, we still give a practical example!

For example,

Suppose now we have such a scenario, the company is holding an activity with 50,000 products to participate in this activity, we need to synchronize the sales volume of each product from the background, so that we can do product analysis for the following activities, how should we deal with the sales synchronization problem?

First sales and inventory data are hot here, but certainly are isolated because of inventory is the requirement of high real-time performance, sales can allow a short delay, so long as can guarantee data to eventual consistency, so at the same time, according to an MQ, we can place an order to update our database products sales.

When we go to check the sales volume, we can not always check the DB so we can handle it through the Redis cache, and we can record the update time of our current query in the cache.

When querying again, the update time in redis data is used as the query condition to query the update time in DB is greater than the record time in our current REDis, thus reducing the number of rows in SQL table scanning (compared with the updated data, the updated data is still a minority).

Based on the above process, we started to write the demo

In this demo we’ve created an ItemSold class and a SkuSold class and ItemSold overrides the Clone method in Cloneable. Then IN the final test class mian METHOD I called the Clone method to copy a new item sales class.

Careful students do not know whether to find a problem when looking at the results? Inside the for loop, I print out the memory addresses of the ItemSold and SkuSold objects respectively.

The SkuSold memory address copied is the same as the original address. The ItemSold memory address copied is not the same as the original address.

In the for loop, we convert data. In general, we do not refer to the underlying model to make the return model. We need to do a layer of transformation to achieve the effect of corrosion. In order to reflect the depth of the copy, so write relatively simple, specific or need to do according to the actual situation.

Shallow copy and deep copy

  • Shallow copy: When the copied object contains only simple data types such as int, float, or immutable objects (strings), these fields are copied directly into the new object. Instead of copying the referenced object, the address of the referenced object is copied to the cloned object

  • Deep copy: Both simple data types and reference object types are copied completely into the new object

For example, it is like two brothers can buy one set of clothes for each of them, and then they live in the same house (shallow copy). When they get married and start a career, the houses are separated and each of them has no influence on each other (deep copy).

The demo above is a shallow copy, so what can we do to make a deep copy?

First let’s take a look at the Cloneable interface provided by Java

The explanation above the interface can be roughly interpreted as:

A class that implements the Cloneable interface implements the clone method of the class to legally copy instances of the class by field. Suppose the clone() method of Object is called on instances that do not implement the Cloneable interface. Leads to throw CloneNotSupporteddException anomalies.

So how do we implement deep copy here?

(1) When rewriting the Clone method in ItemSold, make a copy of SkuSold (because we can only get a shallow copy of the List object, then iterate through the shallow copy of the List object and call the Clone method of the reference object to achieve the deep copy).

We might have to consider recursion if there were multiple levels of reference objects, but the code would look a lot more complicated.

Second: write an object to the stream and then pull it out of the stream through serialization

Both of these are actually possible, but either way, deep copy takes more time and space than shallow copy, so it’s a good idea. There are already a number of utility classes for both shallow and deep copies

  • Deep copy :SerializationUtils
  • Shallow copy :BeanUtils

thinking

In view of the above business scenario we can also through other ways of commodity sales statistics, can again through a MQ to increase sales at the same time to update the redis cache, but we need to pay attention to is in for some core business data and non-core business data as far as possible don’t share a consumer group, prevent influence the consumption rate of the core data. At the same time, when we do design, we should think about the advantages and disadvantages of doing so, the development cost and so on.

In other places we can use the prototype model, we PUSH notification in hair loose activities, for example, for platform millions and millions, even hundreds of millions of users to send notice of the contents of the basic are the same just PUSH the user is not the same as or some special field value changes, the prototype model will be used to do here, At the same time to enable multiple threads to do push, need to pay attention to the thread safety issues here, so inside each thread to do a copy object.

conclusion

The prototype mode is easy to use, but we need to modify the Clone method of the prototype object every time we have a Clone base class or reference object, which is not in accordance with our open and closed principle

In general, this pattern is not recommended unless the object is very expensive to create, or it is used in some special scenarios. Finally, I won’t share the details of some unusual patterns, but I will summarize them later and start to share behavioral patterns.

I’m Aobing, the more you know, the more you don’t know, thank you for your talent: likes, favorites and comments, we’ll see you next time!


This article is constantly updated. You can search “Santaizi Aobing” on wechat and read it for the first time. Reply [Information] There are the interview materials and resume templates for first-line big factories prepared by me.