设计模式——原型模式

本文介绍了原型设计模式,包括浅拷贝和深拷贝的概念及实现方式,通过多利羊克隆的示例进行阐述。同时讨论了深克隆对单例模式的影响,并列举了原型模式在Spring和JDK中的应用及其适用场景。
摘要由CSDN通过智能技术生成

一、原型模式介绍

原型设计模式(Prototype Pattern)是指原型实例指定创建对象的种类,并且通过复制这些原型以创建新的对象。

二、原型模式分类

1、浅克隆
2、深克隆

三、原型模式代码实例

场景实例

现有一只羊Dolly,年龄为1,颜色为白色,它的伴侣羊名为Jack,年龄为2,颜色为黑色

1)浅拷贝

浅拷贝介绍

(1)对于基本数据类型的成员变量,浅拷贝会直接进行至传递,将该属性复制一份给新的对象。(堆里产生新的对象)
(2)对于引用数据类型的成员变量(数组、类的对象),浅拷贝进行引用传递,即将该成员变量的引用值(内存地址)复制给一份新的对象(此时堆中未产生新的对象)。在此情况下,对该成员变量的修改会影响到另一个成员变量的值。
(3)浅拷贝一般使用默认的clone()方法实现。

浅拷贝实现多利羊克隆
//1.饿汉式(静态变量)

//原型类
public class Sheep implements Cloneable {
    private String name;
    private int age;
    private String color;
    public Sheep friend;
    public Sheep(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }
	/*getter,setter方法*/
    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", color='" + color + '\'' +
                ", friend=" + friend +
                '}';
    }

    //克隆该实例,使用默认克隆方法完成
    @Override
    public Object clone() throws CloneNotSupportedException{
        Sheep sheep = null;
        try{
            sheep = (Sheep) super.clone();//默认clone()方法
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
        return sheep;
    }
}
public class Client {
    public static void main(String[] args) throws Exception{
        //传统方法
        Sheep sheep =  new Sheep("Dolly",1,"白色");
        sheep.setFriend(new Sheep("jack",2,"黑色"));
        Sheep sheep1 = (Sheep) sheep.clone();
        Sheep sheep2 = (Sheep) sheep.clone();
        Sheep sheep3 = (Sheep) sheep.clone();
        Sheep sheep4 = (Sheep) sheep.clone();
        System.out.println(sheep.hashCode()+" friend"+sheep.getFriend().hashCode());
        System.out.println(sheep1.hashCode()+" friend"+sheep1.getFriend().hashCode());
        System.out.println(sheep2.hashCode()+" friend"+sheep2.getFriend().hashCode());
        System.out.println(sheep3.hashCode()+" friend"+sheep3.getFriend().hashCode());
        System.out.println(sheep4.hashCode()+" friend"+sheep4.getFriend().hashCode());
        ...
    }
}
1554874502 friend1846274136
1639705018 friend1846274136
1627674070 friend1846274136
1360875712 friend1846274136
1625635731 friend1846274136
...

优缺点
(1)优点:基本属性均实现克隆。
(2)缺点:引用类型未实现克隆。

2)深拷贝

深拷贝基本介绍

(1)将整个对象,包括对象的引用类型进行拷贝。
(2)实现方法: 1)重写clone()方法;2)对象序列化

(1)重写clone()方法实现多利羊克隆
//重写clone()方法
public class Sheep implements Cloneable {
    private String name;
    private int age;
    private String color;
    public Sheep friend;
    public Sheep(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    public Sheep getFriend() {
        return friend;
    }

    public void setFriend(Sheep friend) {
        this.friend = friend;
    }

    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", color='" + color + '\'' +
                ", friend=" + friend +
                '}';
    }
    //克隆该实例,使用默认克隆方法调用默认克隆方法,对引用类型重写克隆方法
    @Override
    public Object clone() throws CloneNotSupportedException{
        Object deep = null;
        deep = super.clone();
	//对引用类型的属性进行单独处理
        Sheep sheep = (Sheep) deep;
        if(friend != null) {            
            sheep.friend = (Sheep) friend.clone();
            return sheep;
        }else{
            return sheep;
        }
    }
}
public class Client {
    public static void main(String[] args) throws Exception{
        //传统方法
        Sheep sheep = new Sheep("Dolly",1,"白色");
        sheep.setFriend(new Sheep("Jack",2,"黑色"));
        Sheep sheep1 = (Sheep) sheep.clone();
        Sheep sheep2 = (Sheep) sheep.clone();
        Sheep sheep3 = (Sheep) sheep.clone();
        Sheep sheep4 = (Sheep) sheep.clone();
        System.out.println("sheep:"+sheep.hashCode()+" friend:"+sheep.getFriend().hashCode());
        System.out.println("sheep:"+sheep1.hashCode()+" friend:"+sheep1.getFriend().hashCode());
        System.out.println("sheep:"+sheep2.hashCode()+" friend:"+sheep2.getFriend().hashCode());
        System.out.println("sheep:"+sheep3.hashCode()+" friend:"+sheep3.getFriend().hashCode());
        System.out.println("sheep:"+sheep4.hashCode()+"  friend:"+sheep4.getFriend().hashCode());
        ...
    }
}
//结果
sheep:1554874502 friend:1846274136
sheep:1639705018 friend:1627674070
sheep:1360875712 friend:1625635731
sheep:1580066828 friend:491044090
sheep:644117698  friend:1872034366
(2)对象序列化实现多利羊克隆
public class Sheep implements Serializable {

    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    private String color;
    public Sheep friend;
    public Sheep(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }
    public Sheep getFriend() {
        return friend;
    }
    public void setFriend(Sheep friend) {
        this.friend = friend;
    }
    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", color='" + color + '\'' +
                ", friend=" + friend +
                '}';
    }

    public Object deepClone(){
        //创建流对象
        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 copyObj = (Sheep) ois.readObject();
            return copyObj;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }finally {
            try{
                bos.close();
                oos.close();
                bis.close();
                ois.close();
			//可用try-with语句避免xxx.close()的步骤,具体操作请自行查阅
            }catch (Exception e){
                e.printStackTrace();
            }
        }

    }
}
public class Client {
    public static void main(String[] args) throws Exception{
        //传统方法
        Sheep sheep = new Sheep("Dolly",1,"白色");
        sheep.setFriend(new Sheep("Jack",2,"黑色"));
        Sheep sheep1 = (Sheep) sheep.deepClone();
        Sheep sheep2 = (Sheep) sheep.deepClone();;
        Sheep sheep3 = (Sheep) sheep.deepClone();;
        Sheep sheep4 = (Sheep) sheep.deepClone();;
        System.out.println("sheep:"+sheep.hashCode()+" friend:"+sheep.getFriend().hashCode());
        System.out.println("sheep:"+sheep1.hashCode()+" friend:"+sheep1.getFriend().hashCode());
        System.out.println("sheep:"+sheep2.hashCode()+" friend:"+sheep2.getFriend().hashCode());
        System.out.println("sheep:"+sheep3.hashCode()+" friend:"+sheep3.getFriend().hashCode());
        System.out.println("sheep:"+sheep4.hashCode()+"  friend:"+sheep4.getFriend().hashCode());
    }
}
//结果
sheep:491044090  friend:1670675563
sheep:2093176254 friend:1854731462
sheep:317574433  friend:885284298
sheep:1389133897 friend:1534030866
sheep:664223387  friend:824909230

优缺点
(1)优点:如果原始对象变化,其克隆对象也会发生相应变化,无需修改代码
(2)缺点:实现深拷贝可能需要比较复杂的代码;对已有拷贝类进行改造时需要修改器源代码,违背了OCP原则

四、深克隆破坏单例模式

若克隆对象是单例对象,则深拷贝会破坏单例模式。为防止此情况,1)单例类不实现Cloneable接口 2)重写clone()方法,让其返回单例对象即可

@Override
protected Object Clone() throws CloneNotSupportedException{
	return INSTANCE;
}

四、原型模式在实际中的运用

Spring中的原型模式

//beans.xml
...
 <!-- scope="prototype" 即 原型模式来创建 -->
 <bean id="id01" class="com.atguigu.spring.bean.Sheep" 
 	scope="prototype"/>
 
...
public static void main(String[] args) {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
		//通过id获取Sheep
		Object bean = applicationContext.getBean("id01");
		System.out.println("bean" + bean); 
		Object bean2 = applicationContext.getBean("id01");
		
		System.out.println("bean2" + bean2); 
		System.out.println(bean == bean2); // false

	}

JDK中的原型模式

//ArrayList实现clone()方法的重写
 /**
     *
     * @return 返回ArrayList实例的拷贝
     */
    public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
    }
    ...
 }

五、原型模式的使用场景

1)类初始化消耗资源过多
2)使用new生成一个对象需要非常繁琐的过程(数据准备,访问权限等)
3)构造函数比较复杂
4)循环体中产生大量对象

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值