设计模式的学习总结-原型模式详解

一、使用场景

1.类初始化消耗资源较多

2.new产生的对象需要非常繁琐的过程(权限认证、数据准备)

3.构造函数比较复杂

4.循环体中产生大量对象

在Spring中原型模式应用的也非常广泛,比如scope="prototype",我们常用的JOSN.parseObject();就是原型模式的一种

二、原型模式的使用

简单克隆

一个简单的原型模式代码,这样的设计。先创建原型接口 Prototype

package Prototype;

public interface Prototype {

    Prototype clone();
}

创建需要具体克隆的对象 PrototypeA

package Prototype;

import lombok.Data;

import java.util.List;

/**
 * Created with IDEA
 * author:Jy
 * Date:2020/3/24
 * Time:15:23
 */
@Data //记得引入lombok包即可
public class PrototypeA implements Prototype {

    private String name;
    private int age;
    private List hobby;

    @Override
    public PrototypeA clone() {
        PrototypeA a = new PrototypeA();
        a.setAge(this.age);
        a.setName(this.name);
        a.setHobby(this.hobby);
        return a;
    }
}

创建Client对象

package Prototype;

/**
 * Created with IDEA
 * author:Jy
 * Date:2020/3/24
 * Time:15:35
 */
public class Client {

    private Prototype prototype;

    public Client(Prototype prototype){
        this.prototype = prototype;
    }

    public Prototype startClone(Prototype startPototype){
        return startPototype.clone();
    }

}

测试代码:

package Prototype;

import java.util.ArrayList;
import java.util.List;

/**
 * Created with IDEA
 * author:Jy
 * Date:2020/3/24
 * Time:15:38
 */
public class PrototypeTest {

    public static void main(String[] args){
        PrototypeA p1 = new PrototypeA();
        p1.setName("JY");
        p1.setAge(21);
        List list =new ArrayList(3);
        list.add("篮球");
        p1.setHobby(list);
        System.out.println(p1);

        Client client = new Client(p1);
        PrototypeA prototypeA = (PrototypeA)client.startClone(p1);
        System.out.println(prototypeA);

        //浅克隆,克隆引用对象,其引用对象主要是克隆地址
        System.out.println("引用对象地址比较:"+ (p1.getHobby() == prototypeA.getHobby()));
        System.out.println("对象地址比较:"+ (p1 == prototypeA ));

    }
}

设计模式的学习总结-原型模式详解_第1张图片

总结:从测试结果可以看出我们克隆的只是引用对象的地址。也就是所有的引用对象都是指向原来的对象,这就是浅克隆。

深度克隆

我们都知道漩涡鸣人,他的分身术,他可以分出许多分身可不是每个分身都能使用九尾,所以我希望实现让每个分身都能使用九尾,那每个九尾都是独一无二了。

先创建鸣人Naruto 对象:

package Prototype.Degree;

import java.util.Date;

/**
 * Created with IDEA
 * author:Jy
 * Date:2020/3/24
 * Time:16:17
 */
public class Naruto {

    private String name;
    private int age;
    private Date brithday;

}

创建九尾Ninetails对象:

package Prototype.Degree;

import java.io.Serializable;

/**
 * Created with IDEA
 * author:Jy
 * Date:2020/3/24
 * Time:16:20
 */
public class Ninetails implements Serializable {

    private String Hurt; //伤害
    private String blood; //血量

}

创建漩涡鸣人XUNaruto对象:

package Prototype.Degree;

import java.io.*;
import java.util.Date;

/**
 * Created with IDEA
 * author:Jy
 * Date:2020/3/24
 * Time:16:25
 */
public class XUNaruto extends Naruto implements Cloneable, Serializable {

    public Ninetails ninetails; //九尾

    public XUNaruto(){
        this.brithday = new Date();
        this.ninetails = new Ninetails();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return this.deepClone();
    }

    public Object deepClone(){
        try{

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);

            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);

            XUNaruto copy = (XUNaruto)ois.readObject();
            copy.brithday = new Date();
            return copy;

        }catch (Exception e){
            e.printStackTrace();
            return null;
        }

    }


    public XUNaruto Deep(XUNaruto xuNaruto){
        XUNaruto x = new XUNaruto();
        x.age = xuNaruto.age;
        x.name = xuNaruto.name;
        x.brithday = new Date();
        x.ninetails = xuNaruto.ninetails;
        return x;
    }
}

创建测试类NarutoTest对象:

package Prototype.Degree;

/**
 * Created with IDEA
 * author:Jy
 * Date:2020/3/24
 * Time:16:36
 */
public class NarutoTest {
    public static void main(String[] args){
        XUNaruto xu = new XUNaruto();
        //深克隆(每个分身都有独立的九尾)
        try {
            XUNaruto a = (XUNaruto)xu.clone();
            System.out.println("深克隆:"+(xu.ninetails == a.ninetails));
        }catch (Exception e){
            e.printStackTrace();
        }
        //浅克隆(每个分身只有九尾的引用)
        XUNaruto xu1 = new XUNaruto();
        XUNaruto b = xu1.Deep(xu1);
        System.out.println("浅克隆:"+(xu1.ninetails == b.ninetails));
    }
}

设计模式的学习总结-原型模式详解_第2张图片

 总结:如果我们克隆的对象是单例对象,这就意味着深克隆会破坏单例。解决思路,禁止深克隆。也可以实现 Cloneable接口,重写 clone() 方法,返回单例对象即可。

你可能感兴趣的:(设计模式-原型模式,java)