java设计模式之原型模式

//参考文档
https://blog.csdn.net/qq_40709468/article/details/82316418

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

使用场景:

1创建对象成本比较大,比如初始化要很长时间的,占用太多CPU的,
新对象可以通过复制已有的对象获得的,如果是相似的对象,则可以对其成员变量稍作修改。
2系统要保存对象状态的,而对象的状态改变很小。
3需要避免使用分层次的工厂类来创建分层次的对象,并且类的对象就只用一个或很少的组合状态!

原型模式的优缺点
原型模式作为一种快速创建大量相同或相似的对象方式,在软件开发种的应用较为广泛,很多软件提供的CTRL+C和CTRL+V操作的就是原型模式的典型应用!

优点
当创建的对象实例较为复杂的时候,使用原型模式可以简化对象的创建过程!提高效率。
缺点
需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的里面,当对已有的类经行改造时需要修改源代码,违背了开闭原则。
在实现深克隆的时需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用的时候,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现相对麻烦。

原型模式适用场景
在以下情况可以考虑使用。

深克隆与浅克隆

  类中的字段对应对象中的属性,这些属性全为基本类型时,subject1----clone---subject2, copy(clone)之后可以保证完全独立的两份,即相对应地将对象subject1的值赋给对象subject2。这种称之为浅拷贝。

  如果类对象的属性中含有引用,比如:private List<String> hobby; 则此时,原型对象和克隆对像中关于属性hobby引用只向的是同一块内存。深克隆需要解决这个问题。解决办法就是再克隆函数中,将相关引用对象重新确定。

测试demo

 

step1 处理原型类(违背开闭原则)。

   实现 Cloneable接口,实现protected Object clone()方法,注意该方法是继承自Object。

  浅拷贝

package java_basic.stu_design_mode.stu_prototype;

import lombok.Data;
//浅拷贝
import java.util.List;
@Data
public class People implements Cloneable{//虽然Cloneable 里面是空的也必须写
    private String name;
    private int age ;
    private List<String> hobby;
    public int getNumber(){
        return age+1000;
    }

    public People(String name, int age, List<String> hobby) {
        System.out.println("调用People的构造方法");
        this.name = name;
        this.age = age;
        this.hobby = hobby;
    }

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

    public String getMessage(){
        return "hello world";
    }

}

换成深拷贝只需将 

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

改一下就行,如下

    @Override
    protected Object clone() throws CloneNotSupportedException {
        People people = (People)super.clone();
        List<String> list = this.getHobby();
        List<String> reList = new ArrayList<>();
        for(int i=0;i<list.size();i++){
            reList.add(list.get(i));
        }
        people.hobby=reList;
        return people;
    }

调用(浅拷贝)

package java_basic.stu_design_mode.stu_prototype;

import org.junit.Test;

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

public class Main {
    @Test
    public void method() {
        List<String> list = new ArrayList();//调用People的构造方法
        list.add("fruit");
        list.add("candy");
        list.add("fishing");
        try {
            People p1 = new People("小明",999,list);
            People p2 = (People)p1.clone();//此时没有调用构造函数
            System.out.println("p1==p2 is  "+(p1==p2));//p1==p2 is  false
            System.out.println("p1.getName()===>"+p1.getName());//p1.getName()===>小明
            System.out.println("p2.getName()===>"+p2.getName());//p2.getName()===>小明
            p2.setName("小刚");
            System.out.println("p1.getName()===>"+p1.getName());//p1.getName()===>小明
            System.out.println("p2.getName()===>"+p2.getName());//p2.getName()===>小刚
            //true 说明引用类型指向的内存是同一块内存,这就属于浅拷贝
            System.out.println("p1.getHobby()==p2.getHobby() "+(p1.getHobby()==p2.getHobby()));//p1.getHobby()==p2.getHobby() true
            System.out.println("p1.getHobby().get(0)===>"+p1.getHobby().get(0));//p1.getHobby().get(0)===>fruit
            System.out.println("p2.getHobby().get(0)===>"+p2.getHobby().get(0));//p2.getHobby().get(0)===>fruit
            p1.getHobby().set(0,"aaa");
            System.out.println(p2.getHobby().get(0));//aaa
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }


}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值