设计模式总纲——原型设计模式

   接上文,在小陈合理的推广下,小陈的铺货量也是愈来愈大,愈来愈多,订单数量也是愈来愈多,大到上市公司,运动品牌专卖店,小到街边饰品小店等都来向小陈这边进货,可是随着订单的愈来愈多,如今天天的订单量都要将近10万量的计数,这时候一件让小陈头疼的事情来了,由于订单量过于多,如今小陈那边的出单机的速率已经跟不上了,由于本来出单机是一单单的打出来的,可是由于订单量过于庞大,速度实在跟不上了,并且小陈认真的观察了一下,订单的格式都是差很少的,都是订单时间,订单数量,订单的产品信息,预约公司的信息,基本上都是信息都是大同小异,咱们先来看看街边小店的订单格式:java

 1 public class OrderInfo {
 2     private String shopName;
 3     
 4     private String shopAddr;
 5     
 6     private String shopMobile;
 7     
 8     private String productName;
 9     
10     private String productNumber;
11 }//由于篇幅缘由,setter/getter方法就不写了

街边小店的订单格式比较简单,就基本信息和地址就是了,可是别看这种街边小店,如今有将近3K家小店跟小陈的公司有合做,每月的营收可很多,有的时候小店的名字、地址、手机同样,就产品和数量不同,又要从新生成一个订单,有的是小店的开了分店,地址不同,可是其余的信息又同样,可是每一个订单新生成的速度忒慢(若是每一个订单都要生成,既浪费虚拟机的性能,并且每次填写相同的信息也要花费不少时间),这个时候,小陈想既然都同样,干脆复制得了,而后再从新填上区别的信息,这样就能够一个订单范本多家公司使用了。(你们能够想一想为何这里不用工厂模式来生成订单?)jvm

  接下来咱们就来看看怎么来进行复制:ide

 1 public class OrderInfo implements Cloneable{
 2     private String shopName;
 3     private String shopAddr;
 4     private String shopMobile;
 5     private String productName;
 6     private String productNumber;
 7 
 8     @Override
 9     protected Object clone() {
10         try {
11             return super.clone();
12         } catch (CloneNotSupportedException e) {
13             e.printStackTrace();
14         }
15         return null;
16     }
17 }//由于篇幅缘由,setter/getter方法就不写了

在这里OrderInfo必须实现Cloneable,让虚拟机知道该对象是可复制的,在这里必须说明一点,clone对象不是Cloneable中的方法,若是咱们点进源代码里面看的话,会发现这个接口是个空接口,那这个clone方法是哪里来的呢?Java里面全部的对象都继承自Object,因此clone方法是Object对象中的方法,咱们这里是重写了他的方法。好了,这样的话,咱们来看看客户端来怎么生成,一家小店有两家分店,除了地址其余的信息都同样的订单了。性能

 1     @Test
 2     public void clien() {
 3         OrderInfo orderInfo = new OrderInfo("饰品小店", "北京王府井大街", "13888888888", "骑士徽章", "10000");
 4         
 5         OrderInfo cloneInfo = (OrderInfo)orderInfo.clone();
 6         
 7         cloneInfo.setShopAddr("北京王府井大街2号");
 8         
 9         System.out.println(orderInfo);
10         System.out.println(cloneInfo);
11     }

OrderInfo [shopName=饰品小店, shopAddr=北京王府井大街, shopMobile=13888888888, productName=骑士徽章, productNumber=10000]
OrderInfo [shopName=饰品小店, shopAddr=北京王府井大街2号, shopMobile=13888888888, productName=骑士徽章, productNumber=10000]ui

这里的话,咱们能够看到除了店面的地址不同,其余的信息所有同样了,这样子就省去了不少成本了,订单的生产速度也快了不止一个级别,小陈很是开心,可是这个时候,订单出单员小A发现了个问题了,当订单是街边小店的订单的时候,订单会没有问题,可是当是上市公司的订单,或者品牌大店的订单的时候,出单就会有问题,小陈观察了一下,原来上市集团的大单的订单格式是下面这种方式的:this

 1 public class OrderInfo implements Cloneable{
 2     private Product productInfo;
 3     private Company company;
 4     
 5     @Override
 6     protected Object clone() {
 7         try {
 8             return super.clone();
 9         } catch (CloneNotSupportedException e) {
10             e.printStackTrace();
11         }
12         return null;
13     }
14 }
15 
16 class Product {
17     private String productName;
18     private String productBuildeAddr;
19     private String productBuildeDate;
20     //...等一系列关于产品的信息,由于篇幅略过
21 }
22 
23 class Company {
24     private String companyName;
25     private String companyAddr;
26     private String companyMobile;
27     //...等一系列关于公司的信息,由于篇幅略过
28 }

大型公司的信息都比较完善,并且他们都把信息封装到了一个个的对象中去了,订单中展现出了一个个的对象,那为何咱们clone的时候不起做用了呢?咱们再来看看客户端的调用:spa

 1     @Test
 2     public void clien() {
 3         OrderInfo orderInfo = new OrderInfo(new Product("骑士徽章","克利夫兰","20160601"),new Company("骑士公司", "北京骑士大道", "13666666666"));
 4         
 5         OrderInfo cloneInfo = (OrderInfo)orderInfo.clone();
 6         
 7         cloneInfo.getCompany().setCompanyAddr("北京骑士大道2号");
 8         
 9         System.out.println(orderInfo);
10         System.out.println(cloneInfo);
11     }

OrderInfo [productInfo=Product [productName=骑士徽章, productBuildeAddr=克利夫兰, productBuildeDate=20160601], company=Company [companyName=骑士公司, companyAddr=北京骑士大道2号, companyMobile=13666666666]]
OrderInfo [productInfo=Product [productName=骑士徽章, productBuildeAddr=克利夫兰, productBuildeDate=20160601], company=Company [companyName=骑士公司, companyAddr=北京骑士大道2号, companyMobile=13666666666]]code

咱们这里就能够看到了clone订单更改了地址以后,原对象也更改了,这里就涉及到了jvm虚拟中的对象的引用了。(说的简单点就是,其实java中的每一个对象在jvm中算是一个引用,引用指向了堆中的对象,而咱们在克隆一个对象时,若是进行了浅拷贝的话,那只是将这个引用复制了一次,而没有对这个对象进行克隆,因此会致使,对象的克隆失败,由于两个引用都指向了堆中的同一个对象,因此在这里咱们就须要进行deep Clone),这里的deep Clone有两种方式:对象

一种就是对须要克隆的对象里面的对象,所有实现clone的方法,那样的话,clone的时候,他就会所有进行复制了,相似上文中的方法blog

 1 class Product implements Cloneable{
 2     @Override
 3     protected Object clone() {
 4         try {
 5             return super.clone();
 6         } catch (CloneNotSupportedException e) {
 7             e.printStackTrace();
 8         }
 9         return null;
10     }
11 }
12 
13 class Company implements Cloneable{
14     @Override
15     protected Object clone() {
16         try {
17             return super.clone();
18         } catch (CloneNotSupportedException e) {
19             e.printStackTrace();
20         }
21         return null;
22     }
23 }

这里必须注意到的是,若是对象里面还有对象的话,那就必须一直实现Cloneable。

 

接下来咱们重点介绍第二种方法:流式克隆

在流式克隆中,咱们这边须要使用到Serializable这个接口,这个接口跟Cloneable同样,也是标识接口,这个接口也是空方法,实现了该接口的对象被标识为可序列化的

 1 public class OrderInfo implements Cloneable,Serializable{
 2     private Product productInfo;
 3     private Company company;
 4     
 5     @Override
 6     protected Object clone() {
 7         try {
 8             ByteArrayOutputStream baos = new ByteArrayOutputStream();
 9             ObjectOutputStream oos = new ObjectOutputStream(baos);
10             oos.writeObject(this);
11             ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
12             ObjectInputStream ois = new ObjectInputStream(bais);
13             return ois.readObject();
14         } catch (IOException e) {
15             e.printStackTrace();
16         } catch (ClassNotFoundException e) {
17             e.printStackTrace();
18         }
19         return null;
20     }
21 }

这里对其进行IO操做是使用JVM中的将对象写到流中是对象的一个拷贝的这一个特性,而源对象仍然保留在了jvm中,因此从新读取出来的话又是一条好对象啦,可是这里必须注意的是若是使用流式拷贝的话,那内部全部的被拷贝的对象都要实现Serializable这个接口,只须要实现Serializable接口便可,不须要其余的操做。而后咱们再执行客户端的操做就能够看到,客户端获得的是两个不一样的对象了。

如今小陈又解决了一个问题了,如今订单的问题也解决了,也再也不会被大量的订单致使出货慢,让客户投诉了,在创业的这段时间遇到了不一样的问题,可是小陈有自信能够一步步的解决掉,下回小陈还会遇到什么样的问题呢?

  欲知下回如何,且听下文分解。

相关文章
相关标签/搜索