设计模式学习笔记(23)——原型模式

版权声明:本文为博主原创,未经博主允许不得转载。 https://blog.csdn.net/weixin_36904568/article/details/90137252

1. 定义

用一个原型对象指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。

2. 使用

(1)简单形式

  • 抽象原型
  • 具体原型:被复制的对象
  • 客户:提出创建对象的请求(明确对象个数)
package PrototypePattern;

/**
 * 抽象接口
 */
public interface Prototype {
    public Object clone();
}

package PrototypePattern;

/**
 * 具体实例
 */
public class PrototypeA implements Prototype {
    @Override
    public Object clone() {
        return new PrototypeA();
    }
}

package PrototypePattern;

public class Test {

    private Prototype prototype;

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

    public Prototype clone(){
        return (Prototype) prototype.clone();
    }

    public static void main(String[] args) {
        Prototype prototype = new PrototypeA();
        Test test = new Test(prototype);
        System.out.println(test.clone());
    }
}

(2)登记形式

  • 抽象原型
  • 具体原型:被复制的对象
  • 客户:提出创建对象的请求(不确定对象个数)
  • 原型管理器:创建具体原型类的对象并记录
package PrototypePattern.RegisterPrototype;

/**
 * 抽象接口
 */
public interface Prototype {
    public Object clone();
    public void setName(String name);
    public String getName();
}

package PrototypePattern.RegisterPrototype;

/**
 * 具体实例
 */
public class PrototypeA implements Prototype {

    private String name;

    @Override
    public Object clone() {
        return new PrototypeA();
    }

    @Override
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "PrototypeA{" +
                "name='" + name + '\'' +
                '}';
    }
}

package PrototypePattern.RegisterPrototype;

/**
 * 具体实例
 */
public class PrototypeB implements Prototype {

    private String name;

    @Override
    public Object clone() {
        return new PrototypeB();
    }

    @Override
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "PrototypeB{" +
                "name='" + name + '\'' +
                '}';
    }
}

package PrototypePattern.RegisterPrototype;

import java.util.HashMap;
import java.util.Map;

/**
 * 原型管理者
 */
public class PrototypeRegistry {

    private Map<String,Prototype> map;

    public PrototypeRegistry(){
        map = new HashMap<>();
    }

    public void add(String id,Prototype prototype){
        map.put(id,prototype);
    }

    public void remove(String id){
        map.remove(id);
    }

    public Prototype getPrototype(String id){
        Prototype prototype = map.get(id);
        if (prototype != null)
            return (Prototype) prototype.clone();
        return null;
    }

}

package PrototypePattern.RegisterPrototype;

public class Test {
    public static void main(String[] args) {
        PrototypeRegistry registry = new PrototypeRegistry();
        //创建原型
        Prototype a = new PrototypeA();
        Prototype b = new PrototypeB();
        registry.add("a",a);
        registry.add("b",b);
        //获取原型的复制
        Prototype c = registry.getPrototype("a");
        c.setName("我是a的复制");
        System.out.println(c);
        //获取原型的复制
        Prototype d = registry.getPrototype("b");
        d.setName("我是b的复制");
        System.out.println(d);
        Prototype e = registry.getPrototype("c");
        System.out.println(e);

    }
}

3. 特点

  • 隐藏创建对象的复杂性
  • 允许在运行时动态改变具体的实现类型
  • 每一个类都必须配备一个克隆方法

4. JAVA的克隆

(1)条件

  • 克隆对象与原对象不是同一个对象。
  • 克隆对象与原对象的类型相同
  • 如果对象x的equals()方法定义其恰当的话,那么x.clone().equals(x)应当成立

(2)分类

浅度克隆

只负责克隆按值传递的数据(基本数据类型、String类型),而不复制它所引用的对象

实现:Java语言的所有类都会继承一个clone()方法

深度克隆

除了浅度克隆要克隆的值外,还负责克隆引用类型的数据。其他被引用的对象的变量将指向被复制过的新对象

实现:利用序列化实现深度克隆。

  1. 先使对象实现Serializable接口
  2. 将对象序列化
  3. 将对象反序列化
 public  Object deepClone() throws IOException, ClassNotFoundException{
        //将对象写到流里
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        //从流里读回来
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
    }

猜你喜欢

转载自blog.csdn.net/weixin_36904568/article/details/90137252