Java-原型-设计模式(四)

说明

原型模式就是通过对原型实例的克隆,制造出一个一模一样的新对象。
实现方式就是实现Cloneable接口,然后重写Object的clone方法。

UML
uml

代码

以Computer为例,三个不同类型的属性。

/**
 * @author ctl
 * @date 2021/1/14
 */
public class Computer implements Cloneable {

    int memory;
    String sys;
    Cpu cpu;

    public Computer(int memory, String sys, Cpu cpu) {
        this.memory = memory;
        this.sys = sys;
        this.cpu = cpu;
    }

    @Override
    protected Computer clone() throws CloneNotSupportedException {
        return (Computer) super.clone();
    }

	public static class Cpu {
	     String type;
	
	      public Cpu(String type) {
	          this.type = type;
	      }
	
	      public String getType() {
	          return type;
	      }
	
	      public void setType(String type) {
	          this.type = type;
	      }
	   }

    public int getMemory() {
        return memory;
    }

    public void setMemory(int memory) {
        this.memory = memory;
    }

    public String getSys() {
        return sys;
    }

    public void setSys(String sys) {
        this.sys = sys;
    }

    public Cpu getCpu() {
        return cpu;
    }

    public void setCpu(Cpu cpu) {
        this.cpu = cpu;
    }
}

测试类

/**
 * @author ctl
 * @date 2021/1/14
 */
public class PrototypeMain {

    public static void main(String[] args) throws CloneNotSupportedException {
        Computer computer = new Computer(16, "mac", new Computer.Cpu("m1"));
        Computer computer2 = computer.clone();
        System.out.println(computer);
        System.out.println(computer2);
        System.out.println(computer.getSys());
        System.out.println(computer2.getSys());
        System.out.println(computer.getCpu());
        System.out.println(computer2.getCpu());
    }
}

结果
结果
Computer对象有三个属性,类型分别是int,String和一个Cpu对象,我们可以看出,Computer对象的地址不是同一个地址,但是Cpu对象的地址是同一个地址,这是为什么呢?
这就涉及到一个深浅拷贝的问题。

浅拷贝:说白了就是两个对象指向一个地址,这时候修改一个对象,另一个可能会受到影响。
深拷贝:就是完完全全互不影响的两个对象,包括其中的属性。

以Computer对象中的三个属性来说:
基本类型不用多说,对于深浅拷贝没有影响。
String类型有些小争议,因为按String对象地址来比较的话,clone出来后的两个对象是一个地址,可以认为是浅拷贝,但因为String存储时的特殊性,修改一个对象也不会对另一个对象造成影响,所以又在结果上可以认为是深拷贝。这里不再赘述,可以专门去了解一下Java对于字符串具体是如何存储的,可以结合着jvm内存模型来一并了解,比如常量池有几种,存在哪里,不同jdk版本有什么区别,等等。
引用类型从结果上来看,自然是浅拷贝,那如何来实现深拷贝呢?

改造后的代码如下:

/**
 * @author ctl
 * @date 2021/1/14
 */
public class Computer implements Cloneable {

    int memory;
    String sys;
    Cpu cpu;

    public Computer(int memory, String sys, Cpu cpu) {
        this.memory = memory;
        this.sys = sys;
        this.cpu = cpu;
    }

    @Override
    protected Computer clone() throws CloneNotSupportedException {
        Computer clone = (Computer) super.clone();
        clone.setCpu(cpu.clone());
        return clone;
    }

    public static class Cpu implements Cloneable {
        String type;

        @Override
        protected Cpu clone() throws CloneNotSupportedException {
            return (Cpu) super.clone();
        }

        public Cpu(String type) {
            this.type = type;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }
    }

    public int getMemory() {
        return memory;
    }

    public void setMemory(int memory) {
        this.memory = memory;
    }

    public String getSys() {
        return sys;
    }

    public void setSys(String sys) {
        this.sys = sys;
    }

    public Cpu getCpu() {
        return cpu;
    }

    public void setCpu(Cpu cpu) {
        this.cpu = cpu;
    }
}

同样的测试类,结果如下:
结果
可以看出,这次Cpu对象的地址也不同了,完成了这个对象的深拷贝。
其实就是把让Cpu这个对象也实现Cloneable接口并重写clone方法,然后在Computer对象的clone方法中调用Cpu的Clone方法再赋值。

总结

原型模式实现起来非常的简单,但在原理上涉及到了深浅拷贝的问题,如果对象中引用对象的层级较深,可能会出一些坑。如果所有属性对象都是自己写的还好,如果是组合了第三方框架中的对象,该对象又没有实现Cloneable接口,实现起来就更费时费力了。

可以看看这篇博客,对原型模式和深浅拷贝讲的更细。
https://blog.csdn.net/zhangjg_blog/article/details/18369201

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值