2021-05-19

 

设计模式--原型模式(Prototype)
原型模式是什么?

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

java中主要是通过clone即浅克隆(ShallowClone)和深克隆(DeepClone)实现原型模式,所以我看有的人也把它叫做克隆模式(下文只讲java中原型模式)。

原型模式的特点是什么?

可以通过原型低成本且高效的复制原型,且复制品不会改变原型(浅克隆可能会改变原型)。

原型模式优缺点

优点:1.效率高,Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良(实际中有可能new更快)。2.可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。

缺点:1.需要为每一个类都配置一个 clone 方法 2.clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。3.当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。

日常用途有哪些?

主要是复制对象(clone,BeanUtils.copyProperties应该也算,但是下文不讲),实际上使用场景有限,且容易出错,具体要视业务场景等实际情况灵活使用。

下面是摘抄的答案

  • 对象之间相同或相似,即只是个别的几个属性不同的时候。
  • 创建对象成本较大,例如初始化时间长,占用CPU太多,或者占用网络资源太多等,需要优化资源。
  • 创建一个对象需要繁琐的数据准备或访问权限等,需要提高性能或者提高安全性。
  • 系统中大量使用该类对象,且各个调用者都需要给它的属性重新赋值

原型模式有几种实现方式?

主要分为深克隆和浅克隆两种。

浅克隆是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。

深克隆不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象

举例来说克隆就像是孙悟空拔毫毛变分身,孙悟空算对象,身上的虱子也是对象。浅克隆的时候克隆出来的孙悟空和原来的孙悟空不一样,

但是两个孙悟空的虱子实际上是一样的,分身孙悟空捏死自己身上的虱子,真身孙悟空身上的虱子也会死;深克隆则真身的虱子没事。

有哪些常见的原型模式写法?

1.浅克隆,基本数据类型可以克隆,引用数据类型不克隆(String除外)

public class Test {
    public static void main(String[] args) throws Exception {
        Person p1 = new Person();
        Person p2 = (Person) p1.clone();
        System.out.println(p2.age + " " + p2.score);
        System.out.println(p2.loc);
        System.out.println(p1.loc == p2.loc);//true
        p1.loc.street = "sh";
        System.out.println(p2.loc);//sh
        p2.loc.street = "sz";
        System.out.println(p1.loc);//sz

    }
}

class Person implements Cloneable {
    int age = 8;
    int score = 100;
    Location loc = new Location("bj", 22);

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

class Location {
    String street;
    int roomNo;

    @Override
    public String toString() {
        return "Location{" +
                "street='" + street + '\'' +
                ", roomNo=" + roomNo +
                '}';
    }

    public Location(String street, int roomNo) {
        this.street = street;
        this.roomNo = roomNo;
    }
}

2.深克隆

基本数据类型和引用数据类型都克隆

/**
 * String不需要进一步深克隆
 */
public class Test {
    public static void main(String[] args) throws Exception {
        Person p1 = new Person();
        Person p2 = (Person)p1.clone();
        System.out.println(p2.age + " " + p2.score);
        System.out.println(p2.loc);

        System.out.println(p1.loc == p2.loc);//false
        p1.loc.street = "sh";
        System.out.println(p2.loc);//bj

        p1.loc.street.replace("sh", "sz");
        System.out.println(p2.loc.street);//bj
    }
}

class Person implements Cloneable {
    int age = 8;
    int score = 100;

    Location loc = new Location("bj", 22);
    @Override
    public Object clone() throws CloneNotSupportedException {
        Person p = (Person)super.clone();
        p.loc = (Location)loc.clone();
        return p;
    }
}

class Location implements Cloneable {
    String street;
    int roomNo;

    @Override
    public String toString() {
        return "Location{" +
                "street='" + street + '\'' +
                ", roomNo=" + roomNo +
                '}';
    }

    public Location(String street, int roomNo) {
        this.street = street;
        this.roomNo = roomNo;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值