栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

创建型设计模式-原型模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

创建型设计模式-原型模式

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。

  • 抽象原型类:规定了具体原型对象必须实现的clone()方法。JDK已经提供了java.lang.Cloneable抽象原型类。

  • 具体原型:实现抽象原型类的clone()方法,它是被复制的对象。

  • 访问类:使用具体原型类的clone()方法来复制新的对象。

  • 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,扔指向原有属性锁指向的对象的内存地址。如JDK中的Object提供的clone()方法。

  • 深克隆:创建一个新对象,属性中应用的其他对象也会被克隆,不再指向原有对象的地址。

public class Object {
	protected native Object clone() throws CloneNotSupportedException;
}

public interface Cloneable {
}

使用new关键字创建对象会调用构造方法,使用clone()方法克隆对象并不会调用构造方法。

什么场景使用原型模式
  • 对象的创建非常复杂,可以使用原型模式快捷创建对象
  • 对性能和安全要求比较高。可以按照我们自己的逻辑来创建对象。
浅克隆实现方式 方式一:java.lang.Cloneable接口
@Data
@RequiredArgsConstructor
@AllArgsConstructor
public class Attribute {
    private int age;
}

实现JDK自带的java.lang.Cloneable接口。

@Data
public class Sheep implements Cloneable {
    private String name;
    private Attribute attribute;


    public Sheep() {
        System.out.println("Sheep构造函数");
    }

    @Override
    protected Sheep clone() throws CloneNotSupportedException {
        System.out.println("开始克隆羊");
        return (Sheep)super.clone();
    }
}
public class Client {
    public static void main(String[] args) throws Exception {
        Attribute attribute = new Attribute(2);

        Sheep prototype = new Sheep();
        prototype.setName("原型羊");
        prototype.setAttribute(attribute);

        Sheep copy = prototype.clone();
        copy.setName("多莉(Dolly)");
        attribute.setAge(3);

        // 原型羊:3
        System.out.println(prototype.getName() +":"+prototype.getAttribute().getAge());
        // 多莉(Dolly):3
        System.out.println(copy.getName()+ ":" + copy.getAttribute().getAge());
    }
}

java.lang.Cloneable#clone()方法就是浅拷贝,所以当拷贝对象的时候只是拷贝对象的内存地址,所以一旦修改原型中的引用对象的属性,那么拷贝出来的对象也会跟着改变。

方式二:BeanUtils.copyProperties(Object source, Object target)

注意事项:

  • BeanUtils.copyProperties() 属于浅拷贝,不同的是它也能拷贝两个不同类型的对象。浅拷贝注意事项
    • 如果对象都是基本类型那么随便使用。
    • 如果对象中的属性有引用类型,只要不去修改对象属性的字段也没什么问题。
    • target 中的存在的属性,source中一定要有,但是source中可以有多余的属性。
    • target、source中的属性要名字相同,才能被赋值,不然的话需要手动赋值。
    • Spring的BeanUtils的copyProperties方法需要对应的属性有getter/setter和无参构造方法。
public class Main {
    public static void main(String[] args) {
        Sheep prototype = new Sheep();
        prototype.setName("原型羊");
        prototype.setAttribute(new Attribute(2));

        Sheep target = new Sheep();
        BeanUtils.copyProperties(prototype, target);
        target.getAttribute().setAge(3);

        System.out.println(prototype.getName() +":"+prototype.getAttribute().getAge());
        System.out.println(target.getName()+ ":" + target.getAttribute().getAge());
    }
}
深拷贝实现

方案一:通过对象序列化实现(每个对象都要实现序列化接口Serializable)。

@Data
@RequiredArgsConstructor
@AllArgsConstructor
public class Attribute implements Serializable {
    private int age;
}

@Data
public class Sheep implements Serializable {
    private String name;
    private Attribute attribute;
}
public class Client {
    public static void main(String[] args) throws Exception {
        Attribute attribute = new Attribute(2);

        Sheep prototype = new Sheep();
        prototype.setName("原型羊");
        prototype.setAttribute(attribute);

        // 对象序列化到文件
        String file = "/Users/mengday/Downloads/oos.txt";
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        oos.writeObject(prototype);
        oos.close();

        // 序列化文件转对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        Sheep copy = (Sheep)ois.readObject();
        copy.getAttribute().setAge(3);

        // 原型羊:2
        System.out.println(prototype.getName() +":"+prototype.getAttribute().getAge());
        // 多莉(Dolly):3
        System.out.println(copy.getName()+ ":" + copy.getAttribute().getAge());
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/995838.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号