程序员:我终于知道啥是原型模式了

作者:千珏

邮箱:[email protected]

公众号:千珏

标题:设计模式之原型模式(转载请标明出处)

Hello,各位观众老爷们大家好,千珏本珏又回来填坑了,按照我本来的想法设计模式应该写玩了,但是人算不如天算啊,最近几个月因为买房然后又买家具的事忙到了现在,还好,中间没有出什么太大的问题,事情已经忙的差不多了,不出意外的话,最近千珏要采取日更模式了,尽量把设计模式这个坑给填完吧,然后后面出一个新的系列的文章。

不说废话了,下面进入正文,原型模式大概可以说是最简单的一个设计模式了,因为java已经直接帮我们实现了,相信这里有小伙伴已经猜到是啥了,没错只要实现 了Cloneable接口,直接调用里面的clone这个方法,就可以直接克隆一个类了,但是他也是最难的设计模式,因为自己实现起来要考虑好多东西。

原型模式

定义

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

定义就是这么简单明了。

例子

上面提到过说java里面已经帮我们实现了原型模式,实现Cloneable接口就行了,下面我们来看一个demo.

public class Test implements Cloneable{
    String age ;
    String name;
    public Test(String age, String name){
        this.age = age;
        this.name = name;
    }
    @Override
    public Test clone(){
        Object object = null;
        try {
            object = super.clone();
        } catch (CloneNotSupportedException exception) {
            throw new RuntimeException(exception);
        }
        return (Test) object;
    }

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

    public static void main(String[] args) throws IOException {
        Test test = new Test("w","20");
        Test test1 = test.clone();
        System.out.println(test);
        System.out.println(test1);
    }
}

程序的输出是

Test{age=‘w’, name=‘20’}
Test{age=‘w’, name=‘20’}

可以看出test1就是完全的复制了test对象。

java里面的clone方法,是浅拷贝,浅拷贝的意思就是如果对象里面有引用对象,拷贝过来的时候不会在生成新的内存块,还是使用老的内存块,看个下面的例子就知道了。

class TestClone{
    String age;
    String name;
    //省略getter,setter
}
public class Test implements Cloneable{
    String age ;
    String name;
    TestClone testClone;
    public Test(String age, String name){
        this.age = age;
        this.name = name;
        testClone = new TestClone();
    }
    @Override
    public Test clone(){
        Object object = null;
        try {
            object = super.clone();
        } catch (CloneNotSupportedException exception) {
            throw new RuntimeException(exception);
        }
        return (Test) object;
    }

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

    public static void main(String[] args) throws IOException {
        Test test = new Test("w","20");
        Test test1 = test.clone();
        System.out.println(test);
        System.out.println(test1);
    }
}

上面的输出结果是

Test{age=‘w’, name=‘20’, testClone=com.wl.common.string.TestClone@1540e19d}
Test{age=‘w’, name=‘20’, testClone=com.wl.common.string.TestClone@1540e19d}

可以看到testclone这个对象的内存块克隆过后输出是一样的,这个不是我们想要的结果,如果我们想在test1中修改TestClone这个对象,那么test这个对象也就会跟着修改这个当然不是我们想要的值。

那么如何使用深拷贝呢,其实很简单就是把上面的TestClone类也实现Cloneable接口就好了。

class TestClone implements Cloneable{
    String age;
    String name;
    //省略getter,setter
     @Override
    public TestClone clone(){
        Object object = null;
        try {
            object = super.clone();
        } catch (CloneNotSupportedException exception) {
            throw new RuntimeException(exception);
        }
        return (TestClone) object;
    }
}
public class Test implements Cloneable{
    String age ;
    String name;
    TestClone testClone;
    public Test(String age, String name){
        this.age = age;
        this.name = name;
        testClone = new TestClone();
    }
    @Override
    public Test clone(){
        Object object = null;
        try {
            object = super.clone();
            ((Test)object).testClone = this.testClone.clone();
        } catch (CloneNotSupportedException exception) {
            throw new RuntimeException(exception);
        }
        return (Test) object;
    }

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

    public static void main(String[] args) throws IOException {
        Test test = new Test("w","20");
        Test test1 = test.clone();
        System.out.println(test);
        System.out.println(test1);
    }
}

改造TestClone过后,再对程序进行输出

Test{age=‘w’, name=‘20’, testClone=com.wl.common.string.TestClone@1540e19d}
Test{age=‘w’, name=‘20’, testClone=com.wl.common.string.TestClone@677327b6}

这个时候我们就完成深克隆了,这个时候就算改变test1对象里面的子对象时,test对象里面的子对象也不会受到干扰,这个才是我们想要的结果。

但是如果有n个子对象的话,实现深拷贝的话就比较困难了,这也是java里面原型对象不可避免的缺点,所以还是要看业务需求呀。

总结

这篇最主要就是讲了java里面如何实现原型模式,java对原型模式实现了语言级的支持,所以实现起来还是挺简单的。相信看完了这一篇文章的看官老爷们应该对原型模式都不陌生了吧。

下一篇预告 策略模式,我们明天见。

猜你喜欢

转载自blog.csdn.net/zjwl199802/article/details/107341350
今日推荐