【Java设计模式】简单学原型模式——变个唐僧看一看

目录

 

说明

目标

实现方式

应用场景

注意事项


说明

1. 五大创建型模式之一,其他还有抽象工厂模式、单例模式、建造者模式、工厂模式。

2. 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象

3. 允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节

目标

1. 深拷贝

2. 浅拷贝(引用类型不自创空间另行储存)


实现方式

在《西游记》中,猪八戒的变身法术,并没有孙悟空那般厉害。让他们变身唐僧,我们可以将猪八戒变身看成深拷贝(只复制一次,不随唐僧变化而变化),而孙悟空的变身看成浅拷贝(不仅外貌相似,同时随唐僧变化而变化)。UML和代码:

【Java设计模式】简单学原型模式——变个唐僧看一看_第1张图片

/**
 * 原型模式
 *
 * @author ZRH
 * @version 1.0.0
 * @date 2020/7/27
 */
public class PrototypeTest {
    public static void main(String[] args) throws Exception {
        // 定义唐僧
        ArrayList skillList = new ArrayList<>();
        skillList.add("喊话技能:悟空救命");
        TangMonk tangMonk = new TangMonk("唐僧", skillList);

        ZhuBaJie zhuBaJie = new ZhuBaJie(tangMonk);
        // 猪八戒的变身,深拷贝(推荐)
        TangMonk tangMonkCopyByZhuBaJie = zhuBaJie.deepClone().getTangMonk();

        SunWuKong sunWuKong = new SunWuKong(tangMonk);
        // 孙悟空的变身,浅拷贝(会受引用类型变化的影响)
        TangMonk tangMonkCopyBySunWuKong = (TangMonk) tangMonk.clone();


        System.out.println("真正的唐僧:" + tangMonk);
        System.out.println("孙悟空变的唐僧:" + tangMonkCopyBySunWuKong);
        System.out.println("猪八戒变的唐僧:" + tangMonkCopyByZhuBaJie);
        System.out.println("================");
        tangMonk.getSkillList().add("嘴遁:紧箍咒");
        System.out.println("真正的唐僧:" + tangMonk);
        System.out.println("孙悟空变的唐僧:" + tangMonkCopyBySunWuKong);
        System.out.println("猪八戒变的唐僧:" + tangMonkCopyByZhuBaJie);


    }


}

/**
 * 唐僧
 * 

* * @author ZRH * @version 1.0.0 * @date 2020-07-21 */ class TangMonk implements Serializable, Cloneable { /** * */ private static final long serialVersionUID = 1L; private String name; /** * 唐僧技能 */ private ArrayList skillList; public TangMonk(String name, ArrayList skillList) { this.name = name; this.skillList = skillList; } public ArrayList getSkillList() { return skillList; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "唐僧,姓名:" + name + ", 技能:" + Arrays.toString(skillList.toArray()); } } /** * 猪八戒(深拷贝,不会因为唐僧技能变化而变化) *

* * @author ZRH * @version 1.0.0 * @date 2020-07-21 */ class ZhuBaJie implements Serializable { /** * */ private static final long serialVersionUID = 1L; public TangMonk tangMonk; public ZhuBaJie(TangMonk tangMonk) { this.tangMonk = tangMonk; } public TangMonk getTangMonk() { return tangMonk; } public ZhuBaJie deepClone() { /** * 深拷贝 - 通过Java原生的对象序列化实现 (推荐) *

* * @return Object * @author ZRH * @date 2020-07-21 * @version 1.0.0 */ //创建流对象 ByteArrayOutputStream bos = null; ObjectOutputStream oos = null; ByteArrayInputStream bis = null; ObjectInputStream ois = null; try { //序列化 bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); //当前这个对象以对象流的方式输出 oos.writeObject(this); //反序列化 bis = new ByteArrayInputStream(bos.toByteArray()); ois = new ObjectInputStream(bis); ZhuBaJie copyObj = (ZhuBaJie) ois.readObject(); return copyObj; } catch (Exception e) { e.printStackTrace(); return null; } finally { //关闭流 try { if (bos != null) { bos.close(); } if (oos != null) { oos.close(); } if (bis != null) { bis.close(); } if (ois != null) { ois.close(); } } catch (Exception e2) { System.out.println(e2.getMessage()); } } } } /** * 孙悟空(浅拷贝,会因为唐僧技能变化而变化) *

* * @author ZRH * @version 1.0.0 * @date 2020/7/27 */ class SunWuKong { public TangMonk tangMonk; public SunWuKong(TangMonk tangMonk) { this.tangMonk = tangMonk; } public TangMonk getTangMonk() { return tangMonk; } }

 


应用场景

1. 类初始化需要消耗非常多的资源,这个资源包括数据、硬件资源等。通过原型拷贝避免这些消耗。

2. 通过new产生一个独享需要非常频繁的数据准备或访问权限。

3. 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。


注意事项

  • 创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率
  • 不用重新初始化对象,而是动态地获得对象运行时的状态
  • 在实现深克隆的时候可能需要比较复杂的代码
  • 对已有的类添加克隆方法时,需要修改其源代码,违背了ocp原则

其他链接

 

【Java设计模式】简单学工厂模式

【Java设计模式】简单学抽象工厂模式

【Java设计模式】简单学建造者模式

【Java设计模式】简单学单例模式

【Java设计模式】简单学原型模式

 

你可能感兴趣的:(Java设计模式,Java)