设计模式之 Prototype(原型模式)通俗理解

1 原型模式定义

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
Prototype 模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。


2 如何使用?

因为 Java 中的提供 clone()方法来实现对象的克隆,所以 Prototype 模式实现一下子变得很简单。

package xx.study.design.prototype;

public class Spoon implements Cloneable{

        String spoonName;
        public void setSpoonName(String spoonName) {
                this.spoonName =spoonName;
        }
        public String getSpoonName() {
                return this.spoonName;
        }
        public Spoon(String spoonName){
                this.spoonName=spoonName;
        }
        public Object clone()
        {
                Object object = null;
                try {
                        object = super.clone();
                } catch (CloneNotSupportedException exception) {
                        System.err.println("AbstractSpoon is not Cloneable");
                }
                return object;
        }


}
package xx.study.design.prototype;

public class PorotypeDemo {
    public static void main(String[] args) {
        Spoon spoon = new Spoon("大勺子");
        System.out.println(spoon.getSpoonName());
        Spoon spoon2 = (Spoon) spoon.clone();
        System.out.println(spoon2.getSpoonName());

    }

}

3 clone拓展

3.1 浅拷贝和深拷贝

浅拷贝:被复制对象的所有值属性都含有与原来对象的相同,而所有的对象引用属性仍然指向原来的对象。(上述案例修改一个对象,会把另外一个对象也会修改)

深拷贝:在浅拷贝的基础上,所有引用其他对象的变量也进行了clone,并指向被复制过的新对象。

也就是说,一个默认的clone()方法实现机制,仍然是赋值。

如果一个被复制的属性都是基本类型,那么只需要实现当前类的cloneable机制就可以了,此为浅拷贝。

如果被复制对象的属性包含其他实体类对象引用,那么这些实体类对象都需要实现cloneable接口并覆盖clone()方法。

3.2 深拷贝实现

package xx.study.design.prototype;

public class SpoonExtend implements Cloneable{

        String spoonName;
        public void setSpoonName(String spoonName) {
                this.spoonName =spoonName;
        }
        public String getSpoonName() {
                return this.spoonName;
        }
        public SpoonExtend(String spoonName){
                this.spoonName=spoonName;
        }
        public Object clone()
        {
                Object object = null;
                try {
                        object = super.clone();
                        String sn=((SpoonExtend)object).getSpoonName();
                        //需要显式地clone其引用成员;如果是类变量 此类实现
                        //Cloneable,setSpoonName(sn.clone()) 
                        ((SpoonExtend)object).setSpoonName(sn+"");

                } catch (CloneNotSupportedException exception) {
                        System.err.println("AbstractSpoon is not Cloneable");
                }
                return object;
        }


}
package xx.study.design.prototype;

public class PorotypeDemo {
    public static void main(String[] args) {
        Spoon spoon = new Spoon("大勺子");
        System.out.println(spoon.getSpoonName());
        Spoon spoon2 = (Spoon) spoon.clone();
        System.out.println(spoon2.getSpoonName());

        spoon.setSpoonName("小勺子");
        System.out.println(spoon.getSpoonName());
        System.out.println(spoon2.getSpoonName());

        System.out.println("测试2");
        SpoonExtend se = new SpoonExtend("大勺子");
        SpoonExtend se2 = (SpoonExtend) se.clone();
        System.out.println(se.getSpoonName());
        System.out.println(se2.getSpoonName());

        se2.setSpoonName("我变了,你变了,吗");

        System.out.println(se2.getSpoonName());
        System.out.println(se.getSpoonName());


    }

}

一句话来说,如果实现完整的深拷贝,需要被复制对象的继承链、引用链上的每一个对象都实现克隆机制。

前面的实例还可以接受,如果有N个对象成员,有M层继承关系,就会很麻烦。

3.3  使用Orika深拷贝

此方式虽然不比原生clone效率高,与其他相比相比效率较高。其他实现可以参考

https://blog.csdn.net/54powerman/article/details/64920431?locationNum=6&fps=1

1依赖

        <dependency>
            <groupId>ma.glasnost.orika</groupId>
            <artifactId>orika-core</artifactId>
            <version>1.5.0</version>
        </dependency>
package xx.study.design.prototype;

import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.converter.ConverterFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;

public class OrikaClone {
    public static void main(String[] args) {
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

        mapperFactory.classMap(Spoon.class,Spoon.class).byDefault().register();
        ConverterFactory converterFactory = mapperFactory.getConverterFactory();
        MapperFacade mapper = mapperFactory.getMapperFacade();

        Spoon s1=new Spoon("勺子");
        Spoon s2 = mapper.map(s1, Spoon.class);
        System.out.println(s1.getSpoonName());
        System.out.println(s2.getSpoonName());
        s2.setSpoonName("小勺");
        System.out.println(s1.getSpoonName());
        System.out.println(s2.getSpoonName());

    }


}

猜你喜欢

转载自blog.csdn.net/h4241778/article/details/107449747