目录
场景
代码实现
有何问题
解决方案
代码改造
模式讲解
原型与new
原型实例与克隆出来的实例
浅度克隆和深度克隆
原型模式的优缺点
思考
何时选用?
相关模式
场景
代码实现
定义订单接口
package com.zsp.bike.day08原型模式;
/**
* 订单的接口
*/
public interface OrderApi {
/**
* 获取订单数量
* @return
*/
public int getOrderProductNum();
/**
* 设置订单产品数量
* @param num 订单产品数量
*/
public void setOrderProductNum(int num);
}
个人订单实现
package com.zsp.bike.day08原型模式;
/**
* 个人订单对象
*/
public class PersonalOrder implements OrderApi{
/**
* 订购人员姓名
*/
private String customerName;
/**
* 产品编号
*/
private String productId;
/**
* 订单产品数量
*/
private int orderProductNum = 0;
@Override
public int getOrderProductNum() {
return this.orderProductNum;
}
@Override
public void setOrderProductNum(int num) {
this.orderProductNum = num;
}
@Override
public String toString() {
return "PersonalOrder{" +
"customerName='" + customerName + '\'' +
", productId='" + productId + '\'' +
", orderProductNum=" + orderProductNum +
'}';
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
}
企业订单实现
package com.zsp.bike.day08原型模式;
/**
* 企业订单对象
*/
public class EnterpriseOrder implements OrderApi{
/**
* 企业名称
*/
private String enterpriseName;
/**
* 产品编号
*/
private String productId;
/**
* 订单产品数量
*/
private int orderProductNum = 0;
@Override
public int getOrderProductNum() {
return this.orderProductNum;
}
@Override
public void setOrderProductNum(int num) {
this.orderProductNum = num;
}
public String getEnterpriseName() {
return enterpriseName;
}
public void setEnterpriseName(String enterpriseName) {
this.enterpriseName = enterpriseName;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
@Override
public String toString() {
return "EnterpriseOrder{" +
"enterpriseName='" + enterpriseName + '\'' +
", productId='" + productId + '\'' +
", orderProductNum=" + orderProductNum +
'}';
}
}
通用的订单处理
package com.zsp.bike.day08原型模式;
/**
* 处理订单的业务对象
*/
public class OrderBusiness {
/**
* 创建订单的方法
* @param order 订单的接口对象
*/
public void saveOrder(OrderApi order){
// 业务要求,当订单数量大于1000,把订单分成两份订单
//1.判断产品数量是否大于1000
while (order.getOrderProductNum() > 1000){
// 2.如果大于,还需要继续拆分
// 2.1 再新建一份订单,跟传入的订单除了数量不一样外,其他都相同
OrderApi newOrder = null;
// 如果属于个人订单
if (order instanceof PersonalOrder){
// 创建相应的新的订单对象
PersonalOrder p2 = new PersonalOrder();
// 然后进行赋值,但是产品数量为1000
PersonalOrder p1 = (PersonalOrder)order;
p2.setCustomerName(p1.getCustomerName());
p2.setProductId(p1.getProductId());
p2.setOrderProductNum(1000);
// 再设置给newOrder
newOrder = p2;
// 如果属于企业订单
}else if(order instanceof EnterpriseOrder){
// 创建相应的订单对象
EnterpriseOrder e2 = new EnterpriseOrder();
// 然后进行赋值,但是产品数量为1000
EnterpriseOrder e1 = (EnterpriseOrder)order;
e2.setEnterpriseName(e1.getEnterpriseName());
e2.setProductId(e1.getProductId());
e2.setOrderProductNum(1000);
// 再设置给newOrder
newOrder = e2;
}
// 2.2 原来的订单保留,把数量设置成减少1000
order.setOrderProductNum(order.getOrderProductNum() - 1000);
// 然后是业务功能处理,省略了,打印输出看一下
System.out.println("拆分生成订单==" + newOrder);
}
//3.不超过1000,那就直接业务功能处理,省略了,打印输出看一下
System.out.println("订单==" + order);
}
}
客户端使用
package com.zsp.bike.day08原型模式;
public class Client {
public static void main(String[] args) {
// 创建订单对象,这里为了演示,直接new了
PersonalOrder op = new PersonalOrder();
// 设置订单数据
op.setOrderProductNum(2925);
op.setProductId("P0001");
op.setCustomerName("张三");
// 这里获取业务处理的类,也直接new了
OrderBusiness ob = new OrderBusiness();
ob.saveOrder(op);
}
}
有何问题
简述:
1.订单处理的对象太过依赖与具体实现,划分的很细。
2.如果要增加一种新类型订单,就要增加新的订单类型支持,就要修改这个订单处理逻辑。
解决方案
原型模式
定义:
解决思路:
代码改造
1.在订单接口里面写一个克隆自己的方法
package com.zsp.bike.day08原型模式;
/**
* 订单的接口
*/
public interface OrderApi {
/**
* 获取订单数量
* @return
*/
public int getOrderProductNum();
/**
* 设置订单产品数量
* @param num 订单产品数量
*/
public void setOrderProductNum(int num);
/**
* 克隆方法
* @return 订单原型的实例
*/
public OrderApi cloneOrder();
}
2.如何克隆?
千万不能return this;这么做客户端获取的都是同一个实例,都是指向同一个内存空间的,对克隆出来的对象实例进行修改会影响到原型对象实例。
应该新建一个实例,把所有属性的值复制到新实例中。
个人订单对象修改
package com.zsp.bike.day08原型模式;
/**
* 个人订单对象
*/
public class PersonalOrder implements OrderApi{
/**
* 订购人员姓名
*/
private String customerName;
/**
* 产品编号
*/
private String productId;
/**
* 订单产品数量
*/
private int orderProductNum = 0;
@Override
public int getOrderProductNum() {
return this.orderProductNum;
}
@Override
public void setOrderProductNum(int num) {
this.orderProductNum = num;
}
@Override
public OrderApi cloneOrder() {
PersonalOrder order = new PersonalOrder();
order.setOrderProductNum(this.orderProductNum);
order.setCustomerName(this.customerName);
order.setProductId(this.productId);
return order;
}
@Override
public String toString() {
return "PersonalOrder{" +
"customerName='" + customerName + '\'' +
", productId='" + productId + '\'' +
", orderProductNum=" + orderProductNum +
'}';
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
}
企业订单修改
package com.zsp.bike.day08原型模式;
/**
* 企业订单对象
*/
public class EnterpriseOrder implements OrderApi{
/**
* 企业名称
*/
private String enterpriseName;
/**
* 产品编号
*/
private String productId;
/**
* 订单产品数量
*/
private int orderProductNum = 0;
@Override
public int getOrderProductNum() {
return this.orderProductNum;
}
@Override
public void setOrderProductNum(int num) {
this.orderProductNum = num;
}
@Override
public OrderApi cloneOrder() {
EnterpriseOrder order = new EnterpriseOrder();
order.setOrderProductNum(this.orderProductNum);
order.setEnterpriseName(this.enterpriseName);
order.setProductId(this.productId);
return order;
}
public String getEnterpriseName() {
return enterpriseName;
}
public void setEnterpriseName(String enterpriseName) {
this.enterpriseName = enterpriseName;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
@Override
public String toString() {
return "EnterpriseOrder{" +
"enterpriseName='" + enterpriseName + '\'' +
", productId='" + productId + '\'' +
", orderProductNum=" + orderProductNum +
'}';
}
}
处理订单的业务对象修改
package com.zsp.bike.day08原型模式;
/**
* 处理订单的业务对象
*/
public class OrderBusiness {
/**
* 创建订单的方法
* @param order 订单的接口对象
*/
public void saveOrder(OrderApi order){
// 业务要求,当订单数量大于1000,把订单分成两份订单
//1.判断产品数量是否大于1000
while (order.getOrderProductNum() > 1000){
// 2.如果大于,还需要继续拆分
// 2.1 再新建一份订单,跟传入的订单除了数量不一样外,其他都相同
OrderApi newOrder = order.cloneOrder();
// 然后进行赋值,产品数量为1000
newOrder.setOrderProductNum(1000);
// 2.2 原来的订单保留,把数量设置成减少1000
order.setOrderProductNum(order.getOrderProductNum() - 1000);
// 然后是业务功能处理,省略了,打印输出看一下
System.out.println("拆分生成订单==" + newOrder);
}
//3.不超过1000,那就直接业务功能处理,省略了,打印输出看一下
System.out.println("订单==" + order);
}
}
通过
用订单的原型实例来指定对象的种类,通过克隆这个原型实例来创建出了一个新的对象实例。
模式讲解
原型模式的功能:
1.通过克隆来创建新的对象实例
2.为克隆出来的新的对象实例复制原型实例属性的值
原型与new
与new不同点在于,new出来的属性是没有值或者只有默认值,克隆出来的实例一般是有值的,它的值就是原型实例的属性的值。
原型实例与克隆出来的实例
克隆完成后,与原型实例是没有关联的,克隆出来的实例属性值发生变化不会影响原型实例。根源在于不是return this; 是复制的,是指向不同内存空间的
需要克隆的类,可以实现java.lang.Cloneable
浅度克隆和深度克隆
原型模式的优缺点
思考
原型模式的本质:克隆生成对象
创建型模式
何时选用?
相关模式