原型模式1
/**
?* 订单的接口
?*/
public interface OrderApi {
??? /**
??? ?* 获取订单产品数量
??? ?* @return 订单中产品数量
??? ?*/
??? public int getOrderProductNum();
??? /**
??? ?* 设置订单产品数量
??? ?* @param num 订单产品数量
??? ?*/
??? public void setOrderProductNum(int num);
}
(2)既然定义好了订单的接口,那么接下来把各种类型的订单实现出来,先看看个人的订单实现,示例代码如下:
/**
?* 个人订单对象
?*/
public class PersonalOrder implements OrderApi{
??? /**
??? ?* 订购人员姓名
??? ?*/
??? private String customerName;
??? /**
??? ?* 产品编号
??? ?*/
??? private String productId;
??? /**
??? ?* 订单产品数量
??? ?*/
??? private int orderProductNum = 0;
???
??? public int getOrderProductNum() {
?????? return this.orderProductNum;
??? }??
??? public void setOrderProductNum(int num) {
?????? this.orderProductNum = num;
??? }??
??? 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;
??? }
??? public String toString(){
?????? return "本个人订单的订购人是="+this.customerName
+",订购产品是="+this.productId+",订购数量为="
+this.orderProductNum;
??? }
}
?????? 再看看企业订单的实现,示例代码如下:
/**
?* 企业订单对象
?*/
public class EnterpriseOrder implements OrderApi{
??? /**
??? ?* 企业名称
??? ?*/
??? private String enterpriseName;
??? /**
??? ?* 产品编号
??? ?*/
??? private String productId;??
??? /**
??? ?* 订单产品数量
??? ?*/
??? private int orderProductNum = 0;
?
??? public int getOrderProductNum() {
?????? return this.orderProductNum;
??? }??
??? 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;
??? }
??? public String toString(){
?????? return "本企业订单的订购企业是="+this.enterpriseName
+",订购产品是="+this.productId+",订购数量为="
+this.orderProductNum;
??? }
}
?????? 有些朋友看到这里,可能会有这样的疑问:看上去上面两种类型的订单对象,仅仅是一个数据封装的对象,而且还有一些数据是相同的,为何不抽出一个父类来,把共同的数据定义在父类里面呢?
?????? 这里有两个考虑,一个是:这里仅仅是一个示意,实际情况远比这复杂,实际开发中不会仅仅是数据封装对象这么简单。另外一个是:为了后续示例的重点突出,这里要学习的是原型模式,因此就没有去抽取父类,以免对象层级过多,影响主题的展示。
(3)实现好了订单对象,接下来看看如何实现通用的订单处理,先把订单处理的对象大概定义出来,示例代码如下:
/**
?* 处理订单的业务对象
?*/
public class OrderBusiness {
??? /**
??? ?* 创建订单的方法
??? ?* @param order 订单的接口对象
??? ?*/
??? public void saveOrder(OrderApi order){
//等待具体实现
??? }
}
?????? 现在的中心任务就是要来实现这个saveOrder的方法,传入的参数是一个订单的接口对象,这个方法要实现的功能:根据业务要求,当订单的预定产品数量超过1000的时候,就需要把订单拆成两份订单。
?????? 那好,来尝试着实现一下,因为预定的数量可能会很大,因此采用一个while循环来处理,直到拆分后订单的数量不超过1000,先把实现的思路写出来,示例代码如下:
public class OrderBusiness {
??? public void saveOrder(OrderApi order){
?????? //1:判断当前的预定产品数量是否大于1000
?????? while(order.getOrderProductNum() > 1000){
?????????? //2:如果大于,还需要继续拆分
?????????? //2.1再新建一份订单,跟传入的订单除了数量不一样外,其它都相同
?????????? OrderApi newOrder = null;
????
?
}
??? }
}
大家会发现,才刚写到第二步就写不下去了,为什么呢?因为现在判断需要拆分订单,也就是需要新建一个订单对象,可是订单处理对象面对的是订单的接口,它根本就不知道现在订单具体的类型,也不知道具体的订单实现,它无法创建出新的订单对象来,也就无法实现订单拆分的功能了。
(4)一个简单的解决办法
有朋友提供了这么一个解决的思路,他说:不就是在saveOrder方法里面不知道具体的类型,从而导致无法创建对象吗?很简单,使用instanceof来判断不就可以了,他还给出了他的实现示意,示意代码如下:
public class OrderBusiness {
??? public void saveOrder(OrderApi order){
?????? while(order.getOrderProductNum() > 1000)
?????????? //定义一个表示被拆分出来的新订单对象
?????????? OrderApi newOrder = null;?????????
???????????if(order instanceof PersonalOrder){
????????????? //创建相应的订单对象
????????????? PersonalOrder p2 = new PersonalOrder();
????????????? //然后进行赋值等,省略了
????????????? //然后再设置给newOrder
????????????? newOrder = p2;
???????????}else if(order instanceof EnterpriseOrder){
??? ?????????? //创建相应的订单对象
????????????? EnterpriseOrder e2 = new EnterpriseOrder();
????????????? //然后进行赋值等,省略了
????????????? //然后再设置给newOrder
????????????? newOrder = e2;
?????????? }?????????
?????????? //然后进行拆分和其它业务功能处理,省略了
?????? }?????
??? }
}
?????? 好像能解决问题,对吧。那我们就来按照他提供的思路,把这个通用的订单处理对象实现出来,示例代码如下:
/**
?* 处理订单的业务对象
?*/
public class OrderBusiness {
??? /**
??? ?* 创建订单的方法
??? ?* @param order 订单的接口对象
??? ?*/
??? public void saveOrder(OrderApi order){
?????? //根据业务要求,当订单预定产品数量超过1000时,就要把订单拆成两份订单
?????? //当然如果要做好,这里的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);???
??? }
}
(5)写个客户端来测试一下,示例代码如下:
public class OrderClient {
??? public static void main(String[] args) {
?????? //创建订单对象,这里为了演示简单,直接new了
?????? PersonalOrder op = new PersonalOrder();
?????? //设置订单数据
?????? op.setOrderProductNum(2925);
?????? op.setCustomerName("张三");
?????? op.setProductId("P0001");
??????
?????? //这里获取业务处理的类,也直接new了,为了简单,连业务接口都没有做
?????? OrderBusiness ob = new OrderBusiness();
?????? //调用业务来保存订单对象
?????? ob.saveOrder(op);
??? }
}
运行结果如下:
拆分生成订单==本个人订单的订购人是=张三,订购产品是=P0001,订购数量为=1000
拆分生成订单==本个人订单的订购人是=张三,订购产品是=P0001,订购数量为=1000
订单==本个人订单的订购人是=张三,订购产品是=P0001,订购数量为=925
?????? 根据订单中订购产品的数量,一份订单被拆分成了三份。
同样的,你还可以传入企业订单,看看是否能正常满足功能要求。
?????? 看起来,上面的实现确实不难,好像也能够通用的进行订单处理,而不需要关心订单的类型和具体实现这样的功能。
???????仔细想想,真的没有关心订单的类型和具体实现吗?答案是“否定的”。
事实上,在实现订单处理的时候,上面的实现是按照订单的类型和具体实现来处理的,就是instanceof的那一段。有朋友可能会问,这样实现有何不可吗?
这样的实现有如下几个问题:
因此,上面的实现是不太好的,把上面的问题再抽象描述一下:已经有了某个对象实例后,如何能够快速简单地创建出更多的这种对象?
比如上面的问题,就是已经有了订单接口类型的对象实例,然后在方法中需要创建出更多的这种对象。怎么解决呢?