• 原型模式--java代码实现


    原型模式

      原型模式,属于对象创建型模式中的一种。通过复制原型对象的方法来创建一个对象实例,且该对象与原对象有相同的数据结构和值。类似我们在备份数据库信息的时候,将数据库中表的结构和数据的一同备份,生成一个数据库文件。

      在Java环境中,要实现原型模式,要理解对象创建、引用和克隆的相关知识,在这里通过简单分析JVM的内存在对象创建、引用和克隆时栈和堆的内容变化,来深入理解原型模式是如何在Java环境中运作的。

    1.简单理解JVM内存中栈和堆

      栈:用来存放函数中定义的基本类型的变量和对象的引用变量。

      堆:则是存放由new创建的对象和数组,对象内存储普通的变量和方法。对象创建后将其地址赋值给栈中的引用变量。

      方法区:也是堆,这里面存放类代码、静态变量、静态方法和字符串常量等。

    2.引用和克隆的区别

    引用的示例图:

    克隆的示意图:

      由示例图我们可以看出,引用,比如person2=person1,栈中两个不同的成员变量指向对中的同一个对象,他们两个的值是一样的,都是该对象在内存中的地址。而克隆是将对象复制一份包括数据结构和值,将复制出的对象的地址赋值给栈中的另外一个成员变量person2。

    3.浅层克隆和深层克隆

      有没有注意到一个问题,如果普通变量是一个引用变量,比如数组,列表或map,那么克隆是否把引用变量(person1中的friends)所引用的对象也给复制一份呢。其实并没有,只是将引用变量的变量名和值复制了一份,他们还是用的同一个引用对象,这就是浅层克隆。如浅层克隆示意图所示。那么如果想要把引用变量所指的对象也复制一份,则需要重新新建一个对应的对象,将值传入对象中,返回给复制后的引用变量person2中的friends中。如深层克隆示意图所示。

    浅层克隆示意图:

    深层克隆示意图:

    4.代码实现

    Person类:

      在Java中克隆该类需实现Cloneable接口,重写了Object的 clone() 方法,该方法会创建和返回一个Person类的一个复制,也就是上述所说的浅层复制。该类中添加了浅层克隆shallowClone()和深层克隆deepClone()。

    package prototype;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Person implements Cloneable{
        //姓名
        private String name;
        //年龄
        private int age;
        //朋友
        private List<String> friends;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public List<String> getFriends() {
            return friends;
        }
        public void setFriends(List<String> friends) {
            this.friends = friends;
        }
        //重写toString方法
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + ", friends=" + friends + "]";
        }
        //浅层克隆
        public Person shallowClone() {
            try {
                return (Person) super.clone();
            } catch (CloneNotSupportedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }
        //深层克隆
        public Person deepClone() {
            try {
                Person person = (Person) super.clone();
                List<String> newFriends = new ArrayList<String>();
                for(String friend : this.getFriends()) {
                    newFriends.add(friend);
                }
                person.setFriends(newFriends);
                return person;
            } catch (CloneNotSupportedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }
    }

    MainClass:

      通过向列表中添加值来测试浅层克隆和深层克隆。具体代码中有注释,请看代码。

    package prototype;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class MainClass {
        public static void main(String[] args) {
            //创建对象person1
            Person person1 = new Person();
            //初始化对象
            person1.setName("zhangsan");
            person1.setAge(20);
            List<String> friends = new ArrayList<String>();
            friends.add("lisi");
            friends.add("wangwu");
            person1.setFriends(friends);
            //person2是浅层克隆
            Person person2 = person1.shallowClone();
            //person3是深层克隆
            Person person3 = person1.deepClone();
            //获取浅层克隆的friends的list对象
            List<String> person2_friends = person2.getFriends();
            //向引用对象中添加值
            person2_friends.add("shallow");
            person2.setFriends(person2_friends);    
            //获取深层克隆的friends的list对象
            List<String> person3_friends = person3.getFriends();
            //向引用对象中添加值
            person3_friends.add("deep");
            person3.setFriends(person3_friends);
            
            System.out.println("原型:"+person1);
            System.out.println("浅层克隆:"+person2);
            System.out.println("深层克隆:"+person3);
        }
    }

    5.结果

      从结果中可以发现,浅层克隆的person2中向friends列表中添加的shallow朋友,而在原型person1中也添加了shallow,验证了前面的说法。深层克隆person3是在person2之前克隆的,所以没有添加shallow朋友,而之后添加的deep朋友也没有影响person1和person2中的friends列表。

    6.总结

      通过结合JVM内存中的栈和堆来解释原型模型,利用Java代码成功测试。可以发现Java中默认是的克隆模式是浅层克隆,不复制引用变量所对应的对象。那么对于深层次的克隆,需要编写对应代码来复制。

  • 相关阅读:
    SQL Server 2005的通用分页存储过程
    沉默的羔羊 赵传
    [转]Ubuntu 10.04 安装 codeblocks10.051 过程详细解析
    VMware7.1.5虚拟机安装Ubuntu 11.10使用share folders共享目录
    【转】libmemcached在windows下的PHP扩展(php_memcached.dll下载)
    Ubuntu升级之后The disk drive for / is not ready yet or not present的解决方法
    基于libmemcached,php扩展memcached的安装
    ubuntu configure的问题解决
    Ubuntu安装CodeBlocks相关问题(不能编译或者编译通过但不能生成可执行文件)
    ubuntu笔记
  • 原文地址:https://www.cnblogs.com/peter_zhang/p/prototype.html
Copyright © 2020-2023  润新知