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

  • 适用场景

       类初始化消耗较多资源

       new产生的一个对象需要非常繁琐的过程(数据准备,访问权限等)

      构造函数比较复杂的过程

      循环体中生成大量对象时

  • 优点

      原型模式性能上比直接new一个对象性能高

      简化创建过程

  • 确定

       必须配备克隆方法

       对克隆复杂对象或对克隆出的对象进行复杂改造时,容易引入风险

       深拷贝和浅克隆要使用得当

示例代码

public class Mail implements Cloneable{
    private String name;

    public String getName() {
        return name;
    }

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

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    private String content;
    private String address;
    @Override
    public Mail clone() throws CloneNotSupportedException {
        return (Mail) super.clone();
    }
}
public class MailUtil {
    public static void sendMail(Mail mail){
        String content="发送给{0},内容为{1},地址未{2}";
        System.out.println(MessageFormat.format(content,mail.getName(),mail.getContent(),mail.getAddress())+mail.toString());


    }
    public static void saveOriginMail(Mail mail){

        System.out.println("存储originMail"+mail.getContent()+mail.toString());


    }
}
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Mail originMail=new Mail();
        originMail.setContent("初始内容");
        for(int i=0;i<5;i++){
            Mail cloneMail= (Mail) (originMail.clone());
            cloneMail.setName("姓名"+i);
            cloneMail.setContent("克隆内容");
            cloneMail.setAddress("地址"+i);
            MailUtil.sendMail(cloneMail);
        }
        MailUtil.saveOriginMail(originMail);
    }
}

输出内容

发送给姓名0,内容为克隆内容,地址未地址0com.pattern.create.prototype.Mail@4554617c
发送给姓名1,内容为克隆内容,地址未地址1com.pattern.create.prototype.Mail@74a14482
发送给姓名2,内容为克隆内容,地址未地址2com.pattern.create.prototype.Mail@1540e19d
发送给姓名3,内容为克隆内容,地址未地址3com.pattern.create.prototype.Mail@677327b6
发送给姓名4,内容为克隆内容,地址未地址4com.pattern.create.prototype.Mail@14ae5a5
存储originMail初始内容com.pattern.create.prototype.Mail@7f31245a

可以发现clone对象不需要调用对象的构造方法,输出了不同对象。

关于深拷贝和浅拷贝

public class Pig implements Cloneable{
    private String name;

    public Pig(String name, Date birthDay) {
        this.name=name;
        this.birthDay=birthDay;
    }

    public String getName() {
        return name;
    }

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

    public Date getBirthDay() {
        return birthDay;
    }

    public void setBirthDay(Date birthDay) {
        this.birthDay = birthDay;
    }

    private Date birthDay;
    @Override
    public Pig clone() throws CloneNotSupportedException {
        return (Pig) super.clone();
    }
}

Test类

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Pig pig1=new Pig("佩奇",new Date(0L));
        Pig pig2=pig1.clone();
        System.out.println(pig1);
        System.out.println(pig2);

        pig1.setName("佩奇1");
        System.out.println(pig1.getName());
        System.out.println(pig2.getName());

        pig1.getBirthDay().setTime(88888888888L);
        System.out.println(pig1.getBirthDay());
        System.out.println(pig2.getBirthDay());

        pig1.setBirthDay(new Date(99999999999999L));
        System.out.println(pig1.getBirthDay());
        System.out.println(pig2.getBirthDay());
    }
}

输出

com.pattern.create.prototype.clone.Pig@4554617c
com.pattern.create.prototype.clone.Pig@74a14482
佩奇1
佩奇
Thu Oct 26 03:21:28 CST 1972
Thu Oct 26 03:21:28 CST 1972
Wed Nov 16 17:46:39 CST 5138
Thu Oct 26 03:21:28 CST 1972

浅拷贝

①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。

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

改为深拷贝的方法

    @Override
    public Pig clone() throws CloneNotSupportedException {
        Pig clonePig=(Pig) super.clone();
        //深克隆
        clonePig.birthDay= (Date) clonePig.birthDay.clone();
        return clonePig;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值