preface

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

In layman’s terms, you take a class as a prototype and then copy another class.

Usage scenarios

Do you find that we use it a lot?

For example, there are BO, DTO and VO in our project, but in the development process, various transformations are needed, such as GET /set. In general, BeanUtils is used to set the attribute value of one class to the attribute value of another class, and then return.

Of course, there is an entity that goes straight from head to tail.

There are tools available for the copy method of BeanUtils in various frameworks, but the Java development manual notes Apache BeanUtils’ poor performance and recommends other frameworks.

Cglib BeanCopier is used here.

Encapsulated utility class

To view the documentation, wrap a utility class:

public class BeanCopierUtils {

    private BeanCopierUtils(a) {}/** * copies the properties of the source object to the target object **@paramSource Source object *@paramTarget Target Object */
    public static void copyProperties(Object source, Object target) {

        BeanCopier beanCopier = BeanCopier.create(source.getClass(), target.getClass(), false);

        beanCopier.copy(source, target, null); }}Copy the code

Does it feel like, if I’m using BeanCopier a lot, and I’m creating objects every time, is that a hassle?

So I came up with the idea of caching!

Treat the BeanCopier as a meta, shared between threads when used.

public class BeanCopierUtils {

    private BeanCopierUtils(a) {}/** * BeanCopier */
    private static Map<String, BeanCopier> CACHE = new HashMap<>();

    /** * copies the properties of the source object to the target object **@paramSource Source object *@paramTarget Target Object */
    public static void copyProperties(Object source, Object target) {
        String cacheKey = source.getClass().getName() + target.getClass().getName();

        BeanCopier beanCopier;

        if(! CACHE.containsKey(cacheKey)) {// Entering here creates a BeanCopier instance and places it in the cache map
            beanCopier = BeanCopier.create(source.getClass(), target.getClass(), false);
            CACHE.put(cacheKey, beanCopier);
        } else {
            beanCopier = CACHE.get(cacheKey);
        }

        beanCopier.copy(source, target, null); }}Copy the code

Then the code can be used happily!

BeanCopierUtils.copyProperties(dto, vo);
Copy the code

At this point, it seems to encapsulate a utility class that has nothing to do with the prototype pattern.

Clone of the object

The clone method must be declared in DTO and VO, so that it can be used in the future

/** * Converts the current object to the target object **@param clazz
 * @param <T>
 * @return
 * @throws Exception
 */
public <T> T clone(Class<T> clazz) throws Exception {

    T target = clazz.newInstance();
    BeanCopierUtils.copyProperties(this, target);
    return target;
}
Copy the code

You can use it now

AccountVO accountVO = accountDTO.clone(AccountVO.class);
Copy the code

For example, if you want to Clone UserVO, you have to pass AddressDTO, then I can’t do anything about it.

As for further evolution, Clone can be abstracted into a public method, such as creating a BaseDTO for all Dtos.

And then there’s the deep copy, which I need to pay attention to.

conclusion

In fact, there are many design patterns at work, but they are used and people don’t see them.

Of course, when used in work, it is all for the sake of agility, and there may not be any Prototype interface defined, but it will be summarized.

Finally, what design patterns are used in your work and the actual application scenarios, please leave a comment and share.

The relevant data

  1. The in-depth design patterns: refactoringguru. Cn/design – patt…
  2. Cover: refactoringguru. Cn/design – patt…