【设计模式】原型模式

  |   0 评论   |   0 浏览

简介

当要创建的对象的类型由一个原型实例确定时,将使用该实例进行克隆以生成新对象。不需要知道任何创建细节,不调用构造函数,可以在运行时来创建对象,可以动态加载类。该模式属于创建型模式。

适用场景

1、类初始化的时候会消耗大量的资源
2、new一个对象需要很多繁琐的步骤
3、构造函数比较复杂
4、在循环中创建大量的类时

优点

1、性能要比使用new高
2、简化了创建对象的过程
3、创建一个新的对象

缺点

1、必须要重写克隆方法(clone())
2、对复杂对象进行克隆会引入风险
3、深拷贝、浅拷贝使用要注意

代码示例

public class Horse implements Cloneable  {
    private String color;
    private Date age;
    public Horse(String color, Date age) {
        this.color = color;
        this.age = age;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    public Date getAge() {
        return age;
    }
    public void setAge(Date age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Horse{" +
                "color='" + color + '\'' +
                ", age=" + age +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

主要是实现Cloneable接口,然后重写clone()方法,测试类:

public class PrototypeTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        Date now = new Date();
        Horse horse = new Horse("白色",now);
        Horse horse2 = (Horse) horse.clone();
        System.out.println(horse);
        System.out.println(horse2);
    }
}

输出为
image.png
把代码修改为如下

public static void main(String[] args) throws CloneNotSupportedException {
        Date now = new Date();
        Horse horse = new Horse("白色",now);
        Horse horse2 = (Horse) horse.clone();
        horse.getAge().setTime(444444444444L);
        System.out.println(horse);
        System.out.println(horse2);
    }

输出结果
image.png
本来只是想对horse的年龄进行修改,但是horse2也被修改掉了,这个其实是浅克隆,如果你需要只修改horse的值,horse2的值不变,那么可以修改为:

@Override
    protected Object clone() throws CloneNotSupportedException {
        Horse horse = (Horse) super.clone();
        //对时间进行深克隆
        horse.age = (Date) horse.age.clone();
        return horse;
    }

所以在使用原型模式的时候,需要小心,有可能一不小心就出问题了。
上面示例源码

源码分析

jdk中应用

ArrayList、HashMap
image.png
image.png
如图都使用了原型模式。

mybatis中应用

image.png
在很多源码中都大量使用了原型模式。

也可以关注我的公众号:程序之声
图片
关注公众号,领取更多资源

本文为博主原创文章,未经博主允许不得转载。