首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

原型模式一

2013-12-15 
原型模式1/**?* 订单的接口?*/public interface OrderApi {??? /**??? ?* 获取订单产品数量??? ?* @return

原型模式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

?????? 根据订单中订购产品的数量,一份订单被拆分成了三份。

同样的,你还可以传入企业订单,看看是否能正常满足功能要求。

9.1.3? 有何问题

?????? 看起来,上面的实现确实不难,好像也能够通用的进行订单处理,而不需要关心订单的类型和具体实现这样的功能。

???????仔细想想,真的没有关心订单的类型和具体实现吗?答案是“否定的”。

事实上,在实现订单处理的时候,上面的实现是按照订单的类型和具体实现来处理的,就是instanceof的那一段。有朋友可能会问,这样实现有何不可吗?

这样的实现有如下几个问题:

  • 既然想要实现通用的订单处理,那么对于订单处理的实现对象,是不应该知道订单的具体实现的,更不应该依赖订单的具体实现。但是上面的实现中,很明显订单处理的对象依赖了订单的具体实现对象。
  • 这种实现方式另外一个问题就是:难以扩展新的订单类型。假如现在要加入一个大客户专用订单的类型,那么就需要修改订单处理的对象,要在里面添加对新的订单类型的支持,这算哪门子的通用处理。

    因此,上面的实现是不太好的,把上面的问题再抽象描述一下:已经有了某个对象实例后,如何能够快速简单地创建出更多的这种对象?

    比如上面的问题,就是已经有了订单接口类型的对象实例,然后在方法中需要创建出更多的这种对象。怎么解决呢?

热点排行