原型模式

1.原型模式的定义与特点

原型(Prototype)模式是一种对象创建型模式,用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。

原型模式的特点:

  1. 由原型对象自身创建目标对象。也就是说,对象创建这一动作发自原型对象本身
  2. 目标对象是原型对象的一个克隆。也就是说,通过Prototype模式创建的对象,不仅仅与原型对象具有相同的结构,还与原型对象具有相同的值
  3. 根据对象克隆深度层次的不同,有浅度克隆与深度克隆。

浅度克隆:克隆的是对象的引用
深度克隆:克隆的是对象的值

2.原型模式的结构和实现

模式的结构:
原型模式包含以下主要角色:

  • 抽象原型类:规定了具体原型对象必须实现的接口。
  • 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
  • 访问类:使用具体原型类中的 clone() 方法来复制新的对象。

结构图如下:
在这里插入图片描述
模式的实现:
     原型模式的克隆分为浅克隆和深克隆,Java 中的 Object 类提供了浅克隆的 clone() 方法,具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆,这里的 Cloneable 接口就是抽象原型类。其代码如下:

/**
 * 原型模式测试类
 */
public class PrototypeTest {

    public static void main(String[] args) throws CloneNotSupportedException {
        ProtoType protoType1 = getProtoType();
        ProtoType protoType2 = getProtoType();
        test("浅度克隆:克隆的是对象的引用", protoType1, protoType1.clone());
        test("\n深度克隆:克隆的是对象的值", protoType2, protoType2.clone2());
    }

    private static ProtoType getProtoType() {
        List<String> ids = new ArrayList<>();
        ids.add("b");
        ids.add("c");
        ProtoType protoType = new ProtoType("a", ids, new ProtoSubType("李四"));
        return protoType;
    }


    private static void test(String pritMsg, ProtoType protoType1, ProtoType protoType2) {
        System.out.println(pritMsg);
        System.out.println(protoType1 == protoType2);
        System.out.println("protoType1 = " + protoType1.toString() + " / protoType2 = " + protoType2.toString());

        protoType2.id = "x";
        protoType2.ids.add("y");
        protoType2.subType.name = "王五";
        System.out.println("protoType1 = " + protoType1.toString() + " / protoType2 = " + protoType2.toString());
    }

}

程序运行结果:

浅度克隆:克隆的是对象的引用
false
protoType1 = {id='a', ids=[b, c], subType={name='李四'}} / protoType2 = {id='a', ids=[b, c], subType={name='李四'}}
protoType1 = {id='a', ids=[b, c, y], subType={name='王五'}} / protoType2 = {id='x', ids=[b, c, y], subType={name='王五'}}

深度克隆:克隆的是对象的值
false
protoType1 = {id='a', ids=[b, c], subType={name='李四'}} / protoType2 = {id='a', ids=[b, c], subType={name='李四'}}
protoType1 = {id='a', ids=[b, c], subType={name='李四'}} / protoType2 = {id='x', ids=[b, c, y], subType={name='王五'}}

/**
 * 原型类
 */
public class ProtoType implements Cloneable {

    public String id;

    public List<String> ids;

    public ProtoSubType subType;

    public ProtoType(String id, List<String> ids, ProtoSubType subType) {
        this.id = id;
        this.ids = ids;
        this.subType = subType;
    }

    /**
     * 浅度克隆:克隆的是对象的引用
     */
    public ProtoType clone() throws CloneNotSupportedException {
        return (ProtoType) super.clone();
    }

    /**
     * 深度克隆:克隆的是对象的值
     */
    public ProtoType clone2() throws CloneNotSupportedException {
        ProtoType protoType = (ProtoType) super.clone();
        List<String> ids = new ArrayList<String>();
        if (this.ids != null) {
            ids.addAll(this.ids);
        }
        protoType.ids = ids;
        protoType.subType = (this.subType.clone());
        return protoType;
    }

    @Override
    public String toString() {
        return "{" + "id='" + id + '\'' + ", ids=" + ids + ", subType=" + subType.toString() + '}';
    }

}
/**
 * 原型类里面的子类对象
 */
public class ProtoSubType implements Cloneable {

    public String name;

    public ProtoSubType(String name) {
        this.name = name;
    }

    public ProtoSubType clone() throws CloneNotSupportedException {
        return (ProtoSubType) super.clone();
    }

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

3.原型模式应用场景

  • 在创建对象的时候,我们不只是希望被创建的对象继承其基类的基本结构,还希望继承原型对象的数据
  • 希望对目标对象的修改不影响既有的原型对象(深度克隆的时候可以完全互不影响)
  • 隐藏克隆操作的细节。很多时候,对对象本身的克隆需要涉及到类本身的数据细节

Demo地址

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值