创建重复对象-场景体验
今天来一个大客户,他要求帮他下100个订单。每个订单除了用户ID,和用户名不同之外,其他个人信息完全相同。
订单类
public class Order{
//id 主键,无实际意义
private String id;
//订单编号
private String orderNo;
//产品编码
private String productNo;
//产品名称
private String productName;
//产品类型
private String productType;
//订单购买数量
private Integer num;
//用户id
private String userId;
//用户名称
private String userName;
//用户电话号码
private String tel;
//用户住址
private String address;
//购买店铺,用于识别改订单是在哪一个店铺下的单。
private Store store;
}
//商店类
public class Store{
//店铺id
private String id;
//店铺名称
private String name;
//店铺负责人
private String head;
//店铺地址
private Strign address;
}
制造数据:
public void copyOrder(){
//专卖店
Store store = new Store();
store.setId("dp001");
store.setName("地球村专卖店");
store.setHead("村长");
store.setAddress("东风东街001号");
//第一个订单
Order order = new Order();
order.setId("111111");
order.setOrderNo("dd001");
order.setProductNo("cp001");
order.setProductName("产品1");
order.setProductType("工具类");
order.setNum(50);
order.setUserId("U001");
order.setUserName("用户1");
order.setTel("17660887362");
order.setAddress("地球村-种花家");
order.setStore(store);
//第二个订单
Order order1 = new Order();
order.setId("111112");
order.setOrderNo("dd002");
order.setProductNo(order.getProductNo());
order.setProductName(order.getProductName());
order.setProductType(order.getProductType());
order.setNum(order.getNum());
order.setUserId("U002");
order.setUserName("用户2");
order.setTel(order.getTel());
order.setAddress(order.getAddress());
order.setStore(store);
...
还要100个
}
上面的代码就是现状,当然也可以使用构造方法,但是过程都是一样的需要大量重复的代码。非常不美观。
解决方案(原型模式)
原型模式可以理解为:将一个完整对象的复制创建过程抽离成一个方法,使我们要创建一个相同对象的时候不需要再依次赋值。
模拟底层实现:
public class Order{
//id 主键,无实际意义
private String id;
//订单编号
private String orderNo;
//产品编码
private String productNo;
//产品名称
private String productName;
//产品类型
private String productType;
//订单购买数量
private Integer num;
//用户id
private String userId;
//用户名称
private String userName;
//用户电话号码
private String tel;
//用户住址
private String address;
//购买店铺,用于识别改订单是在哪一个店铺下的单。
private Store store;
public Order clone(){
Order order1 = new Order();
order1.setId(this.id);
order1.setOrderNo(this.orderNo);
order1.setProductNo(this.productNo);
order1.setProductName(this.productName);
order1.setProductType(this.productType);
order1.setNum(this.num);
order1.setUserId(this.userId);
order1.setUserName(this.userName);
order1.setTel(this.tel);
order1.setAddress(this.address);
order1.setStore(this.store);
return order1;
}
}
我们使用的时候:
public void copyOrder(){
//专卖店
Store store = new Store();
store.setId("dp001");
store.setName("地球村专卖店");
store.setHead("村长");
store.setAddress("东风东街001号");
//第一个订单
Order order = new Order();
order.setId("111111");
order.setOrderNo("dd001");
order.setProductNo("cp001");
order.setProductName("产品1");
order.setProductType("工具类");
order.setNum(50);
order.setUserId("U001");
order.setUserName("用户1");
order.setTel("17660887362");
order.setAddress("地球村-种花家");
order.setStore(store);
//第二个订单
Order order1 = order.clone();
order.setId("111112");
order.setOrderNo("dd002");
order.setUserId("U002");
order.setUserName("用户2");
...
之后的100个相同
}
通过上述方法使原本赋值操作的工作量大量减少,只需要关注自己个性化的赋值即可。
上面的clone方法是完全我自己写的用来模拟的,Java为我们提供了更好的实现,不需要我们去做上面无聊的赋值工作:
只需要Order类实现Cloneable接口,重写clone方法,在这个方法里面调用supper.clone()方法就好了。
public class Order{
//id 主键,无实际意义
private String id;
//订单编号
private String orderNo;
//产品编码
private String productNo;
//产品名称
private String productName;
//产品类型
private String productType;
//订单购买数量
private Integer num;
//用户id
private String userId;
//用户名称
private String userName;
//用户电话号码
private String tel;
//用户住址
private String address;
//购买店铺,用于识别改订单是在哪一个店铺下的单。
private Store store;
@Override
public Order clone(){
Order order1 = new Order();
try {
order1 = (Order) super.clone();
}catch (Exception e){
System.out.println(e.getMessage());
}
return order1;
}
}
有兴趣的未来大佬们可以去看一下clone的源码,这里用的super.clone()是Object中的clone方法。这个方法是native的方法(本地方法)。Java中,用native关键字修饰的函数表明该方法的实现并不是在Java中去完成,而是由C/C++去完成,并被编译成了.dll,由Java去调用。方法的具体实现体在dll文件中,对于不同平台,其具体实现应该有所不同。用native修饰,即表示操作系统,需要提供此方法,Java本身需要使用。
clone主要做的就是开创新的空间,将原对象的数据复制过去,再给返回引用。在Java里面所有的类如果重写clone方法就都是个性化的处理了。但是需要注意的是这个native的clone是浅拷贝。也就是在对象中还有对象的话,内部的对象clone之后还是原来的对象。
以咱们的代码举例:
在Order类中有一个属性是Store的实例。在上面的clone执行之后如果改变clone之后的实例中的store属性,原本的order中的store属性也会改变。
在上面“copyOrder”代码的最后一行增加如下:
System.out.println("order2"+order1);
System.out.println("order:"+order);
System.out.println("改变前order1:"+order1.getStore());
System.out.println("改变前order:"+order.getStore());
order1.getStore().setAddress("地球村-鹰酱家门头房");
System.out.println("改变后order1:"+order1.getStore());
System.out.println("改变前order:"+order.getStore());
可以看到,我们只改变了order1实例中store的address属性,但是order的对应属性也跟着一起变了。
如何解决上面的浅拷贝?
原型模式定义
原型模式(Prototype Pattern)用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式之一。
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。文章来源:https://www.toymoban.com/news/detail-606284.html
定义是引用自:菜鸟教程-原型模式文章来源地址https://www.toymoban.com/news/detail-606284.html
到了这里,关于创造型模式-原型模式(场景体验-》方案解决===代码图解)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!