原型模式(Prototype Pattern)

23种软件设计模式完整教程

介绍

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

意图:

克隆对象、同时保证性能。

使用场景:

类初始化消耗资源较多。

new 产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)

构造函数比较复杂。

循环体中生产大量对象时。

优点:

性能提高。

逃避构造函数的约束。

缺点:

配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。

使用建议:

原型模式已经与 Java 融为浑然一体,大家可以随手拿来使用,比如我们平时多用的:BeanUtils工具类。

两种实现:

(实现一)浅克隆:

         hobbies复制的不是值,而是引用的地址,引用对象仍然指向原来的对象,原有对象改变,由其克隆的所有对象均改变, 这显然不是我们想要的结果。

package com.knowledge.system.software_design_pattern.prototype_pattern.course_instance;

public interface Prototype {
    Prototype clone();
}
package com.knowledge.system.software_design_pattern.prototype_pattern.course_instance;

import java.util.List;

/**
 * @program: demo-pom
 * @description:
 * @author: bo.hu
 * @create: 2020-01-20 17:45
 **/
public class ConcretePrototype implements Prototype {

    private String name;
    private Integer age;
    private List<String> hobbies;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public List getHobbies() {
        return hobbies;
    }

    public void setHobbies(List hobbies) {
        this.hobbies = hobbies;
    }

    @Override
    public ConcretePrototype clone() {
        ConcretePrototype concretePrototype=new ConcretePrototype();
        concretePrototype.setAge(this.getAge());
        concretePrototype.setHobbies(this.getHobbies());
        concretePrototype.setName(this.getName());
        return concretePrototype;
    }
}
package com.knowledge.system.software_design_pattern.prototype_pattern.course_instance;

import com.alibaba.fastjson.JSON;

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

/**
 * @program: demo-pom
 * @description: 客户端
 * @author: bo.hu
 * @create: 2020-01-20 17:53
 **/
public class Client {
    private Prototype prototype;

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

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

    public static void main(String[] args) {
        ConcretePrototype c=new ConcretePrototype();
        c.setName("hubo");
        c.setAge(23);
        List<String> testList=new ArrayList<>();
        testList.add("ceshi");
        c.setHobbies(testList);
        System.out.println(c);
        ConcretePrototype clone=(ConcretePrototype) new Client(c).startClone(c);
        System.out.println(clone);
        System.out.println(JSON.toJSONString(c.getHobbies()));
        System.out.println(JSON.toJSONString(clone.getHobbies()));
        testList.add("hahahah");
        c.setHobbies(testList);
        System.out.println(JSON.toJSONString(c.getHobbies()));
        System.out.println(JSON.toJSONString(clone.getHobbies()));

    }
}

(实现二)深克隆

package com.knowledge.system.software_design_pattern.prototype_pattern.course_instance;

import java.io.*;
import java.util.Date;

/**
 * @program: demo-pom
 * @description: 猴子
 * @author: bo.hu
 * @create: 2020-01-21 14:09
 **/

class Monkey {
    public int height;
    public int weight;
    public Date birthday;
}

class JinGuBang implements Serializable{
    public float h=100;
    public float d=10;
    public void big(){
        this.d*=2;
        this.h*=2;
    }
    public void small(){
        this.d/=2;
        this.h/=2;
    }
}

class QiTianDaSheng extends Monkey implements Cloneable ,Serializable {

    public JinGuBang jinGuBang;

    public QiTianDaSheng() {
        this.birthday = new Date();
        this.jinGuBang = new JinGuBang();
    }

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

    private Object deepClone() {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);

            QiTianDaSheng copy = (QiTianDaSheng) ois.readObject();
            copy.birthday=new Date();
            return copy;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public QiTianDaSheng shallowClone(QiTianDaSheng target){
        QiTianDaSheng qiTianDaSheng=new QiTianDaSheng();
        qiTianDaSheng.height=100;
        qiTianDaSheng.weight=1000;
        qiTianDaSheng.jinGuBang=target.jinGuBang;
        qiTianDaSheng.birthday=new Date();
        return qiTianDaSheng;
    }
}

class Test{
    public static void main(String[] args) {
        QiTianDaSheng qiTianDaSheng=new QiTianDaSheng();
        try {
            QiTianDaSheng deepClone=(QiTianDaSheng)qiTianDaSheng.clone();
            System.out.println("深克隆:"+(qiTianDaSheng.jinGuBang==deepClone.jinGuBang));
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        QiTianDaSheng shallowClone=qiTianDaSheng.shallowClone(qiTianDaSheng);
        System.out.println("浅克隆:"+(qiTianDaSheng.jinGuBang==shallowClone.jinGuBang));

    }
}

日常开发中原型模式的使用:

BeanUtils的使用:

package com.knowledge.system.software_design_pattern.prototype_pattern.myself_instance;

import lombok.Data;

import java.math.BigDecimal;
import java.util.Date;

/**
 * @program: demo-pom
 * @description:
 * @author: bo.hu
 * @create: 2020-01-20 17:37
 **/
@Data
public class Person{
    private String name;
    private Integer age;
    private BigDecimal money;
    private IDcarkd iDcarkd;
    @Data
    public static class IDcarkd {
        private String num;
        private Date year;
    }
}

 

package com.knowledge.system.software_design_pattern.prototype_pattern.myself_instance;

import lombok.Data;

import java.math.BigDecimal;
import java.util.Date;

/**
 * @program: demo-pom
 * @description:
 * @author: bo.hu
 * @create: 2020-01-21 15:39
 **/
@Data
public class PersonVo {
    private String name;
    private String age;
    private BigDecimal money;
    private Person.IDcarkd iDcarkd;
    private Test test;
    @Data
    public static class IDcarkd {
        private String num;
        private Date year;
    }

    @Data
    public static class Test{
        private String name;
        private Date date;
    }
}
package com.knowledge.system.software_design_pattern.prototype_pattern.myself_instance;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.beans.BeanUtils;

import java.math.BigDecimal;
import java.util.Date;

public class BeanUtilsTest {
    public static void main(String[] args) {
        Person person = new Person();
        person.setAge(23);
        person.setMoney(new BigDecimal("23.092"));
        person.setName("test");

        Person.IDcarkd iDcarkd = new Person.IDcarkd();
        iDcarkd.setNum("12");
        iDcarkd.setYear(new Date());

        person.setIDcarkd(iDcarkd);

        Person personClone = new Person();
        BeanUtils.copyProperties(person, personClone);

        System.out.println(JSON.toJSONString(personClone));
        String name=new String("dahghg");
        person.setName(name);
        person.setMoney(new BigDecimal("83751987598357.009"));
        iDcarkd.setNum("9898375");
        person.setIDcarkd(iDcarkd);
        //数组、实体对象、集合----不支持复制,也即BeanUtils的对象克隆是浅克隆。
        System.out.println(JSON.toJSONString(personClone));


        PersonVo vo=new PersonVo();
        BeanUtils.copyProperties(person,vo);
        System.out.println(JSON.toJSONString(vo, SerializerFeature.WriteMapNullValue));
    }
}

 

JSON工具的使用:

略。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值