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

设计模式(四)之原型模式

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

设计模式(四)之原型模式

文章目录
  • 1、原型模式
    • 1.1、传统方式实现
    • 1.2、原型模式实现克隆
    • 1.3、Spring中原型模式的使用
    • 1.4、浅拷贝与深拷贝
    • 1.5、总结

1、原型模式

原型模式也属于创建型模式,所以其本质也是在于类的创建。原型模式指对类进行克隆。

以克隆羊为例:

1.1、传统方式实现

我们看看传统的写法

羊类:

public class Sheep {
    private String name;
    private int age;
    private String color;
    //...构造方法,toString方法,get、set
}

我们传统的写法对它怎么进行克隆呢

public class Client {
    public static void main(String[] args) {
        Sheep sheep = new Sheep("肖恩", 12, "红色");
        Sheep sheep1 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep2 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep3 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        Sheep sheep4 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
        System.out.println(sheep.toString());
        System.out.println(sheep1.toString());
        System.out.println(sheep2.toString());
        System.out.println(sheep3.toString());
        System.out.println(sheep4.toString());
    }

在传统的方式中,我们使用原有的这个对象,进行重复new新对象,并每次获取原有对象,进行克隆。

优点:比较好理解,简单易操作

缺点:

  1. 每次需要获取原有对象,若对象比较复杂,则效率很低。
  2. 总是需要初始化对象,而不是动态的获得对象运行时状态,不够灵活
1.2、原型模式实现克隆

Java中Object内是所有类的根类,Object类提供了一个clone()方法,该方法可以将一个Java对象进行克隆,但是实现clone()方法必须实现Cloneable接口,该接口表示该类能够复制且具有复制的能力。这就会用到原型模式。

public class Sheep1 implements Cloneable {
    private String name;
    private int age;
    private String color;
    //...构造方法,toString方法,get、set
    @Override
    protected Object clone() {
        Sheep1 sheep = null;
        try {
            sheep = (Sheep1)super.clone();
        } catch (CloneNotSupportedException e) {
            System.out.println(e.getMessage());
        }
        return sheep;
    }
}

实现Cloneable方法,并且重写了clone方法。

public class Client1 {
    public static void main(String[] args) {
        Sheep1 sheep = new Sheep1("肖恩", 12, "红色");
        Sheep1 sheep1 = (Sheep1)sheep.clone();
        Sheep1 sheep2 = (Sheep1)sheep.clone();
        Sheep1 sheep3 = (Sheep1)sheep.clone();
        Sheep1 sheep4 = (Sheep1)sheep.clone();
        System.out.println(sheep.toString());
        System.out.println(sheep1.toString());
        System.out.println(sheep2.toString());
        System.out.println(sheep3.toString());
        System.out.println(sheep4.toString());
        System.out.println(sheep1==sheep);//false
    }
}

具体的clone方法可以去源代码内去看。原型模式实现克隆羊就完成了,这样我们改初始化属性或者添加新属性后也不用管任何地方,clone()方法都可以。他是创建一个新对象,不是说他还是原对象。

1.3、Spring中原型模式的使用

Spring中bean的创建其实就是原型模式的应用。

在bean.xml中创建bean我们可以指定scope为原型模式。

在我们创建bean后,调用applicationContext.getBean()方法时其实就等同于刚才写的clone()方法,都是属于原型模式的应用。

1.4、浅拷贝与深拷贝

先看一下,在拷贝过程中,我们拷贝的属性都是常用类型,那如果属性是对象呢?

public class Sheep implements Cloneable {
    private String name;
    private int age;
    private String color;
    public Sheep friend;

    //...构造方法,toString方法,get、set
    @Override
    protected Object clone() {
        Sheep sheep = null;
        try {
            sheep = (Sheep)super.clone();
        } catch (CloneNotSupportedException e) {
            System.out.println(e.getMessage());
        }
        return sheep;
    }
}

对象加了一个属性,friend,然后我们对其进行克隆,看一看他的属性是重新克隆还是只是改了引用。

public class Client {
    public static void main(String[] args) {
        Sheep sheep = new Sheep("jack", 12, "红色");
        sheep.friend = new Sheep("tom",11,"黑色");
        Sheep sheep1 = (Sheep)sheep.clone();
        Sheep sheep2 = (Sheep)sheep.clone();
        Sheep sheep3 = (Sheep)sheep.clone();
        Sheep sheep4 = (Sheep)sheep.clone();
        System.out.println(sheep.toString());
        System.out.println(sheep1.toString());
        System.out.println(sheep2.toString());
        System.out.println(sheep3.toString());
        System.out.println(sheep4.toString());
        System.out.println(sheep1.friend==sheep.friend);//true
    }
}

可以看出他只是将引用拿过来,并没有对其中的对象进行重新创建。这就是浅拷贝,只是对对象进行一个拷贝,没有对其属性也进行拷贝。

所有引入深拷贝,不仅对对象进行拷贝,并且对对象的所有属性进行克隆拷贝。

实现方式:

  1. 重写clone()方法

    public class Sheep implements Cloneable {
        private String name;
        private int age;
        private String color;
        public Sheep friend;
        //...构造方法,toString方法,get、set
        @Override
        protected Object clone() throws CloneNotSupportedException{
            Object sheep = null;
            sheep = super.clone();
            Sheep sheep1 = (Sheep)sheep;
            if(friend==null){
                return sheep1;
            }
            sheep1.friend = (Sheep) friend.clone();
            return sheep1;
        }
    }
    
    Sheep sheep = new Sheep("jack", 12, "红色");
    sheep.friend = new Sheep("tom",11,"黑色");
    Sheep sheep1 = (Sheep)sheep.clone();
    System.out.println(sheep1.friend==sheep.friend);//false
    
  2. 使用序列化实现

    public class Sheep implements Serializable {
        private String name;
        private int age;
        private String color;
        public Sheep friend;
        //...构造方法,toString方法,get、set
        
        
        public Object sheepClone(){
            ByteArrayOutputStream bos =  null;
            ObjectOutputStream oos =  null;
            ByteArrayInputStream bis = null;
            ObjectInputStream ois = null;
    
            try{
                bos = new ByteArrayOutputStream();
                oos = new ObjectOutputStream(bos);
                //当前这个对象流的方式输出
                oos.writeObject(this);
    
                //反序列化
                bis = new ByteArrayInputStream(bos.toByteArray());
                ois = new ObjectInputStream(bis);
                Sheep sheep = (Sheep) ois.readObject();
                return sheep;
            }catch (Exception e){
                e.printStackTrace();
                return null;
            }finally {
                try{
                    bos.close();
                    oos.close();
                    bis.close();
                    ois.close();
                }catch (Exception e){
                    System.out.println(e.getMessage());
                }
            }
        }
    }
    
    Sheep sheep = new Sheep("jack", 12, "红色");
    sheep.friend = new Sheep("tom",11,"黑色");
    Sheep sheep1 = (Sheep) sheep.sheepClone();
    System.out.println(sheep1==sheep);//false
    System.out.println(sheep1.friend==sheep.friend);//false
    

    这样通过序列化反序列化进行了克隆,推荐使用这种方法。

原型模式最主要就是对对象的拷贝,拷贝的对象与原对象不同,是一个新对象。

1.5、总结

优点:

  • 可以利用原型模式简化对象的创建过程,尤其是对一些创建过程繁琐,包含对象层级比较多的对象来说,使用原型模式可以节约系统资源,提高对象生成的效率。
  • 可以很方便得通过改变值来生成新的对象:有些对象之间的差别可能只在于某些值的不同;用原型模式可以快速复制出新的对象并手动修改值即可。

缺点:

  • 对象包含的所有对象都需要配备一个克隆的方法,这就使得在对象层级比较多的情况下,代码量会很大,也更加复杂。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/686796.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

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

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