JAVA设计模式之原型模式

原型模式

定义

用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。

结构与说明

在这里插入图片描述
Prototype:声明一个克隆自身的接口,用来约束想要克隆自己的类,要求它们克隆

ConcretePrototype:实现Prototype接口的类,这些类真正实现克隆自身的功能

Client:使用原型的客户端,首先要获取到原型实例对象,然后通过原型实例克隆自身来创建新的对象实例。

代码

public interface Prototype {
    public Prototype clone();
}
public class ConcretePrototype1 implements Prototype{
    @Override
    public Prototype clone() {
        Prototype prototype = new ConcretePrototype1();
        return prototype;
    }
}
public class Client {
    private Prototype prototype;

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

    public void operation(){
        Prototype newPrototype = prototype.clone();
    }
}

不使用设计模式

instanceof判断类型,然后New对象赋值,增加内容不符合开闭原则

使用设计模式

在这里插入图片描述

功能

(1)通过克隆创建新的对象实例。

(2)另一个克隆出来的对象实例复制原型实例属性的值。

原型与new

克隆方法使用new来实现,只是类似于new 而不是就是new。

克隆方法得到的实例通常有值,其中值是原型对象的值,new对象一般没有值,或者只有默认值。

克隆出来的实例不会影响到原型实例。
C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images

Java中的克隆方法

java中提供了clone方法,定义在Object类中。需要克隆功能的类,只需要实现java.lang.Cloneable接口,接口没有实现的方法,是一个标志接口。

实现Cloneable接口,重写 clone(调用父类,注意修饰符public)

浅度克隆和深度克隆

(1)浅度克隆:只负责克隆按值传递的数据(基本数据类型、String类型)

(2)深度克隆:除了浅度克隆要克隆的值外,还负责克隆引用类型的数据,基本上就是被克隆实例所有的属性的数据都会被克隆出来。

(3)深度克隆还有一个特点,如果被克隆的对象里面的属性数据是引用类型,属性的类型也是对象,那么需要一直递归的克隆下去。这意味着如果要深度克隆成功,必须要整个克隆所涉及的对象都要正确实现克隆方法,如果没有正确实现克隆,就会导致克隆失败。

原型管理器

如果系统中原型的数目不固定,系统中的原型可以被动态的创建和销毁,那么需要在系统中维护一个当前可用的原型注册表,这个注册表被称为原型管理器。

把原型当成资源的话,原型管理器就相当于一个资源管理器,只不过缓存和管理的是原型实例,除了向原型管理器中添加原型通过new创造对象,其它时候都是通过向原型管理器来请求原型实例,然后通过克隆方法来获取新的对象实例,这就可以实现动态管理或动态切换。

public interface Prototype {
    public Prototype clone();
    public String getName();
    public void setName(String name);
}

public class ConcretePrototype1 implements Prototype{
    private String name;

    @Override
    public Prototype clone() {
        ConcretePrototype1 prototype1 = new ConcretePrototype1();
        prototype1.setName(name);
        return prototype1;
    }

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

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

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

public class ConcretePrototype2 implements Prototype{
    private String name;

    @Override
    public Prototype clone() {
        ConcretePrototype2 prototype2 = new ConcretePrototype2();
        prototype2.setName(name);
        return prototype2;
    }

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

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

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

public class PrototypeManager {

    private  static Map<String,Prototype> map = new HashMap<String,Prototype>();

    private PrototypeManager(){}

    public  synchronized static void setPrototype(String prototypeId,Prototype prototype){
       map.put(prototypeId,prototype);
    }

    public synchronized static void removePrototype(String prototypeId){
        map.remove(prototypeId);
    }


    public synchronized static Prototype getPrototype(String prototypeId){
        Prototype prototype = map.get(prototypeId);
        if(prototype == null){
            System.out.println("无原型被注册");
        }
        return prototype;
    }
}

public class Client {
    public static void main(String[] args) {
        Prototype prototype = new ConcretePrototype1();
        PrototypeManager.setPrototype("prototype1",prototype);

        Prototype p3 = PrototypeManager.getPrototype("prototype1").clone();
        p3.setName("a1");
        System.out.println(p3);

        Prototype prototype1 = new ConcretePrototype2();
        PrototypeManager.setPrototype("prototype2",prototype1);

        Prototype p4 = PrototypeManager.getPrototype("prototype2").clone();
        p4.setName("a2");

        System.out.println(p4);
    }
}

优缺点

1、对客户端隐藏具体的实现类型

2、在运行时动态改变具体的实现类型

3、深度克隆方法实现会比较困难

本质

克隆生成对象

何时选用

1、如何一个系统想要独立于它想要使用的对象时,可以使用原型模式,让系统只面向接口编程,系统需要新的对象时,通过克隆原型来得到。

2、如果需要实例化的类是在运行时动态指定,可以使用原型模式,通过克隆原型来得到实例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值