java电子发票_看我72变——Java设计模式——原型模式

bdc001b5827e0700f8533d3649132868.png

Java设计模式——原型模式

面向对象编程,时时刻刻与对象打交道,有时候获取一个实例化的对象非常麻烦。比如一个需要访问数据库关联大量数据表才能得到一个实例,比如对象的属性非常非常多,通过构造函数获取对象需要初始化很多对象,比较麻烦,浪费内存。类似这样的场景就需要原型模式解决问题啦。

原型模式:说白了就是更简单的获取相同或相似的对象实例。可以理解为复制克隆

下面了解两个概念

浅克隆:克隆出来的对象实例一模一样,对象的属性如果是引用数据类型,那么它们指向同一个地址值。无论是修改原来的对象,还是修改克隆出来的对象,只要是引用数据类型修改了,那么两个对象同时被修改,因为他们共享同一地址值。

深克隆:克隆出来的对象实例也是一模一样的,但是他们的引用属性也被克隆了,两个对象虽然一模一样,但是没有任何关联。修改其中一个对象,不影响另一个对象。

需求:实现电子发票对象的克隆,电子发票具有票头、票号、名称、单位、公司、颜色、监制印章、公司印章、是否有效等等对象属性。制作一张发票还是很麻烦的,所以利用原型模式快速复制发票对象,高效完成需求。

提供一个原型接口,便于原型管理和业务扩展。

/** * @description: 原型模式原型接口 * @author: lmc * @create: 2019-05-29 20:32 **/public interface Prototype {    /**     * @description: 获取浅克隆对象     * @return java.lang.Object     * @date 2019/5/29 20:35     * @author lmc     */    Prototype getShallowCloneInstance() throws CloneNotSupportedException;    /**     * @description: 获取深克隆对象     * @return com.lmc.gp12380.pattern.prototype.Prototype     * @date 2019/5/30 21:15     * @author lmc     */    Prototype getDeepCloneInstance(Prototype prototype);}

提供一个工具类,利用序列化实现深克隆;当然,也可以按照业务需求,把需要克隆类的所有引用对象类全部实现浅克隆,这样也是一个深克隆对象了,但是这种方法很麻烦,容易忽略对象没有去实现浅克隆。

/** * @description: 原型工具类 * @author: lmc * @create: 2019-05-30 21:27 **/public class PrototypeUtil {    /**     * @description: 通过序列化获取一个深度克隆的对象     * @param prototype     * @return com.lmc.gp12380.pattern.prototype.Prototype     * @date 2019/5/30 21:34     * @author lmc     */    public static Prototype getSerializInstance(Prototype prototype){        try {            ByteArrayOutputStream bos = new ByteArrayOutputStream();            ObjectOutputStream oos = new ObjectOutputStream(bos);            oos.writeObject(prototype);            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());            ObjectInputStream ois = new ObjectInputStream(bis);            Prototype copy = (Prototype)ois.readObject();            bos.flush();            bos.close();            ois.close();            return copy;        }catch (Exception e){            e.printStackTrace();        }        return null;    }}

电子发票印章图片类

/** * @description: 电子发票印章图片 * @author: lmc * @create: 2019-05-29 21:21 **/public class Image implements Serializable,Prototype,Cloneable {    /**     * 颜色     */    private String color="red";    /**     * 高度     */    private Integer height=10;    /**     * 宽度     */    private Integer width=8;    public String getColor() {        return color;    }    public void setColor(String color) {        this.color = color;    }    public Integer getHeight() {        return height;    }    public void setHeight(Integer height) {        this.height = height;    }    public Integer getWidth() {        return width;    }    public void setWidth(Integer width) {        this.width = width;    }    @Override    public String toString() {        return "Image{" +                "color='" + color + ''' +                ", height=" + height +                ", width=" + width +                '}';    }    @Override    protected Object clone() throws CloneNotSupportedException {        return super.clone();    }    public Prototype getShallowCloneInstance() throws CloneNotSupportedException {        return (Prototype) clone();    }    public Prototype getDeepCloneInstance(Prototype prototype) {        return PrototypeUtil.getSerializInstance(prototype);    }}
/** * @description: 电子印章 * @author: lmc * @create: 2019-05-29 21:19 **/public class Seal implements Serializable,Cloneable,Prototype {    /**     * 印章名称     */    private String name;    /**     * 已知图片     */    private Image image;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Image getImage() {        return image;    }    public void setImage(Image image) {        this.image = image;    }    @Override    public String toString() {        return "Seal{" +                "name='" + name + ''' +                ", image=" + image +                '}';    }    @Override    protected Object clone() throws CloneNotSupportedException {        return super.clone();    }    public Prototype getShallowCloneInstance() throws CloneNotSupportedException {        return (Prototype) clone();    }    public Prototype getDeepCloneInstance(Prototype prototype) {        return PrototypeUtil.getSerializInstance(prototype);    }}
/** * @description: 电子发票 * @author: lmc * @create: 2019-05-29 20:36 **/public class Invoice implements Cloneable,Serializable,Prototype {    /**     * 票头     */    private String ticketHeader;    /**     * 票号     */    private int ticketNo;    /**     * 发票联名称     */    private String name;    /**     * 发票联颜色     */    private String color;    /**     * 发票联公司     */    private String company;    /**     * 公司印章     */    private Seal companySeal;    /**     * 监制印章     */    private Seal supervisedSeal;    /**     * 是否有效     */    private Boolean effective;    public String getTicketHeader() {        return ticketHeader;    }    public void setTicketHeader(String ticketHeader) {        this.ticketHeader = ticketHeader;    }    public int getTicketNo() {        return ticketNo;    }    public void setTicketNo(int ticketNo) {        this.ticketNo = ticketNo;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getColor() {        return color;    }    public void setColor(String color) {        this.color = color;    }    public String getCompany() {        return company;    }    public void setCompany(String company) {        this.company = company;    }    public Seal getCompanySeal() {        return companySeal;    }    public void setCompanySeal(Seal companySeal) {        this.companySeal = companySeal;    }    public Seal getSupervisedSeal() {        return supervisedSeal;    }    public void setSupervisedSeal(Seal supervisedSeal) {        this.supervisedSeal = supervisedSeal;    }    public Boolean getEffective() {        return effective;    }    public void setEffective(Boolean effective) {        this.effective = effective;    }    @Override    protected Object clone() throws CloneNotSupportedException {        return super.clone();    }    @Override    public String toString() {        return "Invoice{" +                "ticketHeader='" + ticketHeader + ''' +                ", ticketNo=" + ticketNo +                ", name='" + name + ''' +                ", color='" + color + ''' +                ", company='" + company + ''' +                ", companySeal=" + companySeal +                ", supervisedSeal=" + supervisedSeal +                ", effective=" + effective +                '}';    }    public Prototype getShallowCloneInstance() throws CloneNotSupportedException {        return (Prototype)clone();    }    public Prototype getDeepCloneInstance(Prototype prototype) {        return PrototypeUtil.getSerializInstance(prototype);    }}

电子发票Invoice类 包含了印章Seal类;Seal印章类包含了Image类 ;Invoice、Seal、Image全部实现了

Prototype、Cloneable、Serializable接口。

clone():是Object类的方法,该方法能够快速复制一个对象,属于浅克隆,引用对象属性不复制。

Cloneable接口:实现该接口才可以调用clone()方法。

Serializable接口:类实现该接口,类的对象才能被序列化和反序列化。

测试代码

/** * @description: 原型模式测试 * @author: lmc * @create: 2019-05-29 21:46 **/public class PrototypeClientTest {    public static void main(String[] args) throws CloneNotSupportedException {        Invoice invoice=new Invoice();        invoice.setColor("bule");        invoice.setTicketNo(1);        invoice.setEffective(false);        invoice.setCompanySeal(new Seal());        //测试浅克隆        //Invoice invoiceClone = (Invoice) invoice.getShallowCloneInstance();        //        Invoice invoiceClone = (Invoice) invoice.getDeepCloneInstance(invoice);        /**         * 验证对象是否同一个。         */        System.out.println("invoice_"+invoice.hashCode());        System.out.println("Clone_invoice_"+invoiceClone.hashCode());        System.out.println("验证对象_"+(invoice==invoiceClone));        /**         * 验证基本数据类型是否相等。         */        System.out.println("getTicketNo_"+invoice.getTicketNo());        System.out.println("Clone_getTicketNo_"+invoiceClone.getTicketNo());        System.out.println("验证基本数据类型_"+(invoice.getTicketNo()==invoiceClone.getTicketNo()));        /**         * 验证引用数据类型是否相等         */        System.out.println("getColor_"+invoice.getColor().hashCode());        System.out.println("Clone_getColor_"+invoiceClone.getColor().hashCode());        System.out.println("验证引用数据类型_"+(invoiceClone.getColor() == invoice.getColor()));        System.out.println("getCompanySeal_"+invoice.getCompanySeal().hashCode());        System.out.println("Clone_getCompanySeal_"+invoiceClone.getCompanySeal().hashCode());        System.out.println("验证引用数据类型_"+(invoice.getCompanySeal() == invoiceClone.getCompanySeal()));         System.out.println("____________________________________________________________");        /**         * 验证基本数据类型修改         */        invoice.setTicketNo(2);        System.out.println("验证基本数据类型修改"+invoice);        System.out.println("验证基本数据类型修改"+invoiceClone);        /**         * 验证基本数据类型保包装类         */        invoice.setEffective(true);        System.out.println("验证基本数据类型包装类"+invoice);        System.out.println("验证基本数据类型包装类"+invoiceClone);        /**         * 验证引用数据类型         */        invoice.getCompanySeal().setName("验证引用数据类型");        System.out.println("验证引用数据类型"+invoice);        System.out.println("验证引用数据类型"+invoiceClone);    }}

测试深克隆结果

b1060ea8f23276c3701d9c660fb06c1a.png

深克隆的对象和原对象 是两个独立的对象,虽然他们的内容相同,但是他们没有任何关联。

测试浅克隆结果

5c1b51d84cc7dbeca744bb4efcbdc3a2.png

浅克隆的对象和原对象也是两个对象,但是他们的引用属性对象是共享同一个对象的。上面修改公司印章,克隆对象的公司印章也修改了。基本数据类型和基本数据类型的包装类型不共享。

浅克隆模型图

f2a03b51f224d48199829d572a8ccc12.png

对于浅克隆:栈内存中基本数据类型存储的是值,引用数据类型存储的是引用地址值。浅克隆对所有的基本数据类型进行拷贝,引用数据类型拷贝引用地址值。注意:对于基本数据类型包装类型、String类型,还有基本数据类型,只要对其进行赋值操作,就相当于重新创建了对象,之前的对象或者值就成了不可达状态,只能被垃圾回收器回收了。虽然基本数据类型的包装类型和String都是引用数据类型,但是无法证明他们是共享同一个地址值(希望大神解惑)。

深克隆模型图

509353945d3de62a047e58c68d27ec8b.png

对于深克隆:深克隆对所有的数据都进行了拷贝,不论是基本数据类型还是引用数据类型。两个对象之间没有任何关联关系,完完全全是独立自主的,虽然他们长得一样。

总结:所有的程序都是为业务服务的,按照业务需求,如果原型模式获取对象更简单,更合理,那么就应该使用原型模式,如果使用原型模式反而让对象的获取更复杂,程序的复杂度提升,可读性下降。就不应该强行使用设计模式。

b7afa4fb537d310daa2a2415fd95aafa.png

本文属于作者原创。

博客地址:https://www.cnblogs.com/programmerkaixin

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值