原型模式-克隆一个对象

这篇具有很好参考价值的文章主要介绍了原型模式-克隆一个对象。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 在开发一个界面的时候,里面有多个Button,这些对象的属性内容相似。如果一个个实例化Button对象,并设置其属性,那么代码量将会增多。

通过一个原型对象克隆出多个一模一样的对象,该模式被称为原型模式。

原型模式-克隆一个对象,设计模式的艺术,原型模式

 图 原型模式

Prototype: 抽象原型类,是声名克隆方法的接口,也可以是具体原型类的公共父类。

ConcretePrototype:具体原型类,实现了克隆方法,在克隆方法中返回自己的一个克隆对象。

Client:客户类,让一个原型对象克隆自身从而创建一个新的对象。

public interface ButtonClone {

    ButtonClone cloneBtn();

}

public class Button implements ButtonClone{

    private Double width;
    private Double height;

    public Double getWidth() {
        return width;
    }

    public void setWidth(Double width) {
        this.width = width;
    }

    public Double getHeight() {
        return height;
    }

    public void setHeight(Double height) {
        this.height = height;
    }

    @Override
    public ButtonClone cloneBtn() {
        Button newBtn = new Button();
        newBtn.setHeight(this.height);
        newBtn.setWidth(this.width);
        return newBtn;
    }
}

1 浅克隆与深克隆

浅克隆,如果源对象的成员变量是值类型,将复制一份给克隆对象,如果源对象的成员变量是引用类型,则将引用对象的地址复制一份给对象。

深克隆,无论源对象的成员变量是值类型还是引用类型,都将复制一份给目标对象。

1.1 浅克隆

Java的Object类提供了一个clone()方法,可以将一个Java对象浅克隆。能实现克隆Java类必须实现一个标识接口Cloneable,表示这个类支持被复制。

public class ConcretePrototype implements Cloneable{

    private String name;

    private String type;

    private List<String> list = new ArrayList<>();

    public ConcretePrototype(String name, String type) {
        this.name = name;
        this.type = type;
    }

    @Override
    public String toString() {
        return "ConcretePrototype{" +
                "name='" + name + '\'' +
                ", type='" + type + '\'' +
                ", list=" + list +
                '}';
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        ConcretePrototype prototype = new ConcretePrototype("实际类型", "浅克隆");
        System.out.println("prototype:" + prototype);
        Object clone = prototype.clone();
        System.out.println("clone:" + clone);

        prototype.list.add("hello");
        System.out.println("clone:" + clone);
    }

}

1.2 深克隆

深克隆,除了对象本身被复制外,对象所包含的所有成员变量也将被复制。在Java中,如果需要实现深克隆,可以通过序列化等方式来实现。需要实例化的对象其类必须实现Serializable接口,否则无法实现序列化操作。

public class CusForm implements Serializable , Cloneable{

    private String name;
    private CusFile cusFile;

    public CusForm(String name, CusFile cusFile) {
        this.name = name;
        this.cusFile = cusFile;
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException, CloneNotSupportedException {
        CusForm cusForm = new CusForm("表单", new CusFile());
        System.out.println(cusForm);
        System.out.println(cusForm.clone()); //java浅克隆,对象成员变量直接复制地址
        CusForm deepCloneObj = cusForm.deepClone();
        System.out.println(deepCloneObj);

//        运行结果
//        CusForm{name='表单', cusFile=com.huangmingfu.prototype.deep.CusForm$CusFile@1b6d3586}
//        CusForm{name='表单', cusFile=com.huangmingfu.prototype.deep.CusForm$CusFile@1ddc4ec2}
//        CusForm{name='表单', cusFile=com.huangmingfu.prototype.deep.CusForm$CusFile@1b6d3586}
    }

    public CusForm deepClone() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        objectOutputStream.writeObject(this);

        ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        return (CusForm) objectInputStream.readObject();
    }

    @Override
    public String toString() {
        return "CusForm{" +
                "name='" + name + '\'' +
                ", cusFile=" + cusFile +
                '}';
    }

    private static class CusFile implements Serializable{}
}

2 原型管理器

将多个原型对象存储在一个集合中供客户端使用,它是一个专门复制克隆对象的工厂。其中定义了一个集合用于存储原型对象。

原型模式-克隆一个对象,设计模式的艺术,原型模式

图 原型管理器

public class DeepClone implements Serializable {
    public DeepClone deepClone()  {
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
            objectOutputStream.writeObject(this);
            ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
            ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
            return (DeepClone)objectInputStream.readObject();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }
}

public class ConcreteA extends DeepClone{

    private final String name = "concreteA";

    @Override
    public String toString() {
        return "ConcreteA{" +
                "name='" + name + '\'' +
                '}' + super.toString();
    }

}

public class ConcreteB extends DeepClone{

    private final String name = "ConcreteB";

    @Override
    public String toString() {
        return "ConcreteB{" +
                "name='" + name + '\'' +
                '}' + super.toString();
    }
}

public class PrototypeManager {

    private final Map<Class<? extends DeepClone>,DeepClone> prototypeMap = new HashMap<>();
    private final Set<Class<? extends DeepClone>> classes = new HashSet<>();

    private PrototypeManager() {}

    private static class HolderClass {
        private final static PrototypeManager instance = new PrototypeManager();
    }

    public static PrototypeManager getInstance() {
        return HolderClass.instance;
    }

    public void addPrototype(DeepClone deepClone) {
        if (classes.add(deepClone.getClass())) {
            prototypeMap.put(deepClone.getClass(),deepClone);
        }
    }

    public DeepClone getClone(Class<? extends DeepClone> cls) {
        DeepClone deepClone = prototypeMap.get(cls);
        if (deepClone == null) {
            throw new RuntimeException("克隆体不存在");
        }
        return deepClone.deepClone();
    }

}

public class Client {

    public static void main(String[] args) {
        ConcreteA concreteA = new ConcreteA();
        ConcreteB concreteB = new ConcreteB();
        PrototypeManager prototypeManager = PrototypeManager.getInstance();

        System.out.println(concreteA);
        System.out.println(concreteB);

        prototypeManager.addPrototype(concreteA);
        prototypeManager.addPrototype(concreteB);
        System.out.println("克隆分割线---------------");
        DeepClone deepCloneA = prototypeManager.getClone(ConcreteA.class);
        DeepClone deepCloneB = prototypeManager.getClone(ConcreteB.class);

        System.out.println(deepCloneA);
        System.out.println(deepCloneB);

//        运行结果
//        ConcreteA{name='concreteA'}com.huangmingfu.prototype.manager.ConcreteA@1b6d3586
//        ConcreteB{name='ConcreteB'}com.huangmingfu.prototype.manager.ConcreteB@4554617c
//        克隆分割线---------------
//        ConcreteA{name='concreteA'}com.huangmingfu.prototype.manager.ConcreteA@30dae81
//        ConcreteB{name='ConcreteB'}com.huangmingfu.prototype.manager.ConcreteB@1b2c6ec2
    }

}

3 适用场景

当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建工厂,通过复制一个已有实例可以提高新实例的创建效率。文章来源地址https://www.toymoban.com/news/detail-588358.html

  1. 创建新对象成本较大。
  2. 对象的状态变化很小,且系统需要保存对象的状态时。
  3. 需要创建许多相似对象。

到了这里,关于原型模式-克隆一个对象的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《设计模式的艺术》笔记 - 面向对象设计原则

    1、单一职责原则         一个类只负责单一功能领域中的相应职责。 2、开闭原则         一个软件实体应当对扩展开放,对修改关闭。即软件实体应当尽量在不修改原有代码的情况下进行扩展。 3、里氏代换原则         所有引用基类的地方必须能透明地使用其子类的对

    2024年01月21日
    浏览(57)
  • 介绍原型模式:快速构建和复制对象的设计模式

    经过瀑布模式之后,我们不禁想要用模型解决更多的问题,最重要的就是不再单向行径。 由此,介绍 原型模式, 所谓原型,就是我们有一个框架或者初始角色。我们可以根据项目的不同,对它进行不同的修改,使它适配。 在软件开发中,经常会遇到需要创建和复制对象的情

    2024年02月12日
    浏览(39)
  • 一网打尽java注解-克隆-面向对象设计原则-设计模式

    注解 :也叫标注,用于包、类、变量、方法、参数上。可以通过反射获取标注。可以在编译期间使用,也可以被编译到字节码文件中,运行时生效。 内置注解 :Java语言已经定义好的注解。 @Overread :用于方法重写。 @Deprecated :标记过时方法。 @SuppressWarnings :指示编译器去

    2024年02月11日
    浏览(44)
  • 一天一个设计模式---原型模式

    原型模式(Prototype Pattern)是一种创建型设计模式,其主要目的是通过复制现有对象来创建新对象,而不是通过实例化类。原型模式允许在运行时动态创建对象,同时避免了耦合与子类化。 在原型模式中,有一个原型对象,它是被复制的对象。新对象通过复制原型对象的属性

    2024年02月04日
    浏览(40)
  • 原型模式——对象的克隆

    可以通过一个原型对象克隆出多个一模一样的对象,该模式被称为原型模式。 在使用原型模式时,需要首先创建一个原型对象,再通过复制这个原型对象来创建更多同类型的对象。 原型模式(Prototype Pattern):使用原型实例指定创建对象的种类,并且通过克隆这些原型创建新

    2024年02月14日
    浏览(30)
  • JAVA设计模式----原型设计模式

    定义 :用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。 类型 :创建类模式 类图 : 原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Prototype类需要具备以下两个条件: 实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只

    2024年02月13日
    浏览(49)
  • 重温设计模式 --- 原型模式

    原型模式 是一种创建型设计模式,它允许我们创建一个对象的副本,而不需要显式地使用构造函数来创建一个新的对象。这种模式通常用于创建那些具有复杂创建过程或需要大量资源的对象。 在原型模式中,我们首先定义一个原型接口,该接口包含一个克隆方法。然后我们

    2024年02月13日
    浏览(49)
  • 设计模式系列-原型模式

    一、上篇回顾 上篇创建者模式中,我们主要讲述了创建者的几类实现方案,和创建者模式的应用的场景和特点,创建者模式适合创建复杂的对象,并且这些对象的每 个组成部分的详细创建步骤可以是动态的变化的,但是每个对象的组装的过程来说可能是相对固定的或者说是

    2024年02月09日
    浏览(43)
  • 设计模式-原型模式

    目录 一、传统方式 二、原型模式  三、浅拷贝和深拷贝 克隆羊问题: 现在有一只羊tom,姓名为: tom,年龄为: 1,颜色为: 白色,请编写程序创建和tom羊属性完全相同的10只羊。 传统的方式的优缺点: 简单易操作。优点是比较好理解。 在创建新的对象时,总是需要重新获取原

    2024年02月16日
    浏览(36)
  • 设计模式5:原型模式

    Prototype Pattern 如果对象的创建成本比较大,可以基于已有的原型对象通过来创建新的对象,节省创建时间。 设计模式之原型模式 实现Cloneable接口的方式。这里就不展开分析浅克隆和深克隆了,后面再专门分析浅克隆和深克隆,不影响对原型模式的理解。 用序列化实现创建对

    2024年02月11日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包