首页 > 其他分享 >原型模式

原型模式

时间:2024-03-27 21:34:50浏览次数:18  
标签:Sheep sheep String color 模式 原型 public name

 

1. 原型模式介绍

  创建对象的种类,并且通过拷贝这些原型,创建新的对象,无需知道如何创建的细节

 

2. 原型模式

  问题:现在有一只羊 tom ,姓名为 : tom, 年龄为: 1 ,颜色为:白色,请编写程序创建和 tom羊属性完全相同的10 只羊

  (1)传统方式解决

public class Sheep {

    private String name;

    private String color;

    private int age;

    public Sheep(String name, String color, int age) {
        this.name = name;
        this.color = color;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", color='" + color + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Client {

    public static void main(String[] args) {

        Sheep sheep = new Sheep("tome", "白色", 1);

        Sheep sheep1 = new Sheep(sheep.getName(), sheep.getColor(), sheep.getAge());
        Sheep sheep2 = new Sheep(sheep.getName(), sheep.getColor(), sheep.getAge());
        Sheep sheep3 = new Sheep(sheep.getName(), sheep.getColor(), sheep.getAge());

        System.out.println(sheep);
        System.out.println(sheep1);
        System.out.println(sheep2);
        System.out.println(sheep3);
    }
}

  优点:比较好理解,简单易操作

  缺点:在创建新的对象时,总是需要重新获取原始对象的属性,如果创建的对象比较复杂时,效率较低;总是需要重新初始化对象,而不是动态地获得对象运行时的状态, 不够灵活

  (2)原型模式(浅拷贝)

public class Sheep implements Cloneable {

    private String name;

    private String color;

    private int age;

    public Sheep friend;

    public Sheep(String name, String color, int age) {
        this.name = name;
        this.color = color;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", color='" + color + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    protected Object clone(){
        Sheep sheep = null;

        try {
            sheep = (Sheep) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return sheep;
    }
}
public class Client {
    public static void main(String[] args) {

        Sheep sheep = new Sheep("tome", "白色", 1);
        sheep.friend = new Sheep("jack","褐色",1);
        Sheep sheep1 = (Sheep) sheep.clone();
        Sheep sheep2 = (Sheep) sheep.clone();

        System.out.println("sheep =" + sheep + "sheep.friend=" + sheep.friend.hashCode());
        System.out.println("sheep1 =" + sheep1 + "sheep1.friend=" + sheep1.friend.hashCode());
        System.out.println("sheep2 =" + sheep2 + "sheep2.friend=" + sheep2.friend.hashCode());

    }
}

   (1)对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。

  (2)对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值

  (3)sheep.friend浅拷贝后还是都指向同一个内存地址

 

  (3)原型模式(深拷贝-重写clone方法)

public class DeepCloneableTarget implements Cloneable, Serializable {

    private static final long serialVersionUID = 1L;

    private String cloneName;

    private String cloneClass;

    public DeepCloneableTarget(String cloneName, String cloneClass) {
        this.cloneName = cloneName;
        this.cloneClass = cloneClass;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class DeepProtoType implements Serializable,Cloneable {

    public String name;

    public DeepCloneableTarget deepCloneableTarget;

    public DeepProtoType() {
        super();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object deep = null;
        deep = super.clone();
        DeepProtoType deepProtoType = (DeepProtoType) deep;
        deepProtoType.deepCloneableTarget  = (DeepCloneableTarget) deepCloneableTarget.clone();

        return deepProtoType;
    }
}
public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {

        DeepProtoType d = new DeepProtoType();
        d.name = "kater";
        d.deepCloneableTarget = new DeepCloneableTarget("ke","le");

        DeepProtoType d1 = (DeepProtoType) d.clone();
        System.out.println("d.name=" + d.name + " d.deepCloneableTarget=" + d.deepCloneableTarget.hashCode());
        System.out.println("d1.name=" + d1.name + " d1.deepCloneableTarget=" + d1.deepCloneableTarget.hashCode());

    }
}

 

  (4)原型模式(深拷贝-对象序列化)推荐

  使用对象序列化的方式不用为每一个引用类型的成员变量都调用一下自身的clone方法所以是比较推荐的方式

public class DeepCloneableTarget implements Cloneable, Serializable {

    private static final long serialVersionUID = 1L;

    private String cloneName;

    private String cloneClass;

    public DeepCloneableTarget(String cloneName, String cloneClass) {
        this.cloneName = cloneName;
        this.cloneClass = cloneClass;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class DeepProtoType implements Serializable,Cloneable {

    public String name;

    public DeepCloneableTarget deepCloneableTarget;

    public DeepProtoType() {
        super();
    }


    public Object deepClone(){
        //创建流对象
        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);
            DeepProtoType object = (DeepProtoType) ois.readObject();
            return object;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }finally {
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
public class Client {
    public static void main(String[] args) {

        DeepProtoType d = new DeepProtoType();
        d.name = "kater";
        d.deepCloneableTarget = new DeepCloneableTarget("ke","le");

        DeepProtoType d1 = (DeepProtoType) d.deepClone();
        System.out.println("d.name=" + d.name + " d.deepCloneableTarget=" + d.deepCloneableTarget.hashCode());
        System.out.println("d1.name=" + d1.name + " d1.deepCloneableTarget=" + d1.deepCloneableTarget.hashCode());

    }
}

  (1)复制对象的所有基本数据类型的成员变量值

  (2)为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象进行拷贝

 

  原型模式:

  (1)创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率;

  (2)不用重新初始化对象,而是动态地获得对象运行时的状态

  (3)如果原始对象发生变化(增加或者减少属性),其它克隆对象的也会发生相应的变化,无需修改代码

  (4)在实现深克隆的时候可能需要比较复杂的代码

  (5)需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有的类进行改造时,需要修改其源代码,违背了开放-封闭ocp原则

标签:Sheep,sheep,String,color,模式,原型,public,name
From: https://www.cnblogs.com/homle/p/18100283

相关文章

  • 实例、构造函数、原型、原型对象、prototype、__proto__、原型链……
    学习原型链和原型对象,不需要说太多话,只需要给你看看几张图,你自然就懂了。prototype表示原型对象__proto__表示原型实例、构造函数和原型对象以error举例图中的error表示axios抛出的一个错误对象(实例)。宇宙的尽头是nullObject.prototype.__proto__===null......
  • [docker] 浅谈Docker:网络模式及从容器内部访问宿主机的IP地址
    0序本文系转载参考文献,属于非原创的笔记类博文。最新结论:从Docker容器内部访问宿主的IP地址的几种方法,推荐基于Bridge模式+--link访问别的服务+172.16.0.1(访问宿主机)。1Docker的网络模式docker是比较流行的容器技术,docker镜像方便程序员对应用统一的要求,打包部......
  • 原来内存条要开启xmp模式
    明明我购买的是3600mhz的内存条,但是在资源管理器里面显示2600mhz问客服才知道需要开始xmp在bios里面开启重启后一看到主板的页面就按F2或delete我一直按都没有反应查阅资料发现应该是主板设置了快速启动,usb键盘在启动时不通电,那么按就没反应然后我在一见到光的时候就强制关......
  • Java商城 免 费 搭 建:鸿鹄云商实现多种商业模式,VR全景到SAAS,应有尽有
    鸿鹄云商b2b2c产品概述【b2b2c平台】,以传统电商行业为基石,鸿鹄云商支持“商家入驻+平台自营”多运营模式,积极打造“全新市场,全新模式”企业级b2b2c电商平台,致力干助力各行/互联网创业腾飞并获取更多的收益。从消费者出发,助力企业构建完整电商交易生态,整合资源,创造更有利的......
  • 双碳目标下基于全球模式比较计划CMIP6与区域气候-化学耦合模式WRF-Chem的未来大气污染
    原文链接:双碳目标下基于全球模式比较计划CMIP6与区域气候-化学耦合模式WRF-Chem的未来大气污染变化模拟教程https://mp.weixin.qq.com/s?__biz=MzUzNTczMDMxMg==&mid=2247599209&idx=7&sn=2fb78bcb18e6ec709853a7595d8822d9&chksm=fa82058ecdf58c9852bf40b62a8198088d10a6bc5a1......
  • Jmeter性能测试 —— 压力模式
    压力模式性能测试中的压力模式有两种。第一种是并发用户模式(虚拟用户模式)并发用户是指虚拟并发用户数,从业务角度,也可以理解为同时在线的用户数。从客户端的角度出发,摸底业务系统各节点能同时承载的在线用户数,可以使用该模式设置目标并发,也就是Jmeter里面的线程数。第二种是R......
  • 浅析JS原型链
    目录实例对象原型对象对象原型短暂总结一下constructor原型链何为原型链呢?就是实例对象和原型对象之间的链接,每一个对象都有原型,原型本身又是对象,原型又有原型,以此类推形成一个链式结构.称为原型链。这里又扯到了另外两个概念了。实例对象>>>先往下看实例对象原型对象>>......
  • Java版直播商城免 费 搭 建:平台规划与常见营销模式,电商源码、小程序、三级分销及详解
    【saas云平台】打造全行业全渠道全场景的saas产品,为经营场景提供一体化解决方案;门店经营区域化、网店经营一体化,本地化、全方位、一站式服务,为多门店提供统一运营解决方案;提供丰富多样的营销玩法覆盖所有经营场景,助力商家成功;系统稳定压倒一切,让商家经营有保障,消费者购物更放心......
  • 二级分销+团队模式+平级奖励的结合!
    二级分销、团队模式和平级奖励,这些元素结合起来,可以构建一种非常有效的销售和激励机制。二级分销,简而言之,就是销售网络有两层。第一层的分销商从公司购买产品,然后销售给第二层的分销商或最终消费者。第二层分销商再将这些产品销售给消费者或发展自己的下级分销商。这种模式有......
  • 设计模式相关
    设计模式的目标设计模式是一种解决问题的思路,提供一种通用的、可重用的解决方案。设计模式的主要目标包括:提高代码的可重用性:设计模式可以使开发人员将经过验证的设计思想和方法应用于新的问题,从而提高代码的可重用性。提高代码的可维护性:设计模式能够提供一种清晰......