博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对多态的理解(基于PHP)
阅读量:5967 次
发布时间:2019-06-19

本文共 8346 字,大约阅读时间需要 27 分钟。

hot3.png

代码中经常遇到多个if else的情况 ,以前对多态理解只限于了解,并没有真正使用过。今天听老大讲了下,把自己的理解帖出来,一下代码均基于PHP实现,不态了解java的多态机制。

首先,我们以订单作为一个例子,操作一个订单的时候,基本上都要基于订单状态,做出相应操作。我们假设一个订单有一下几种状态:1,created(创建状态,等待工作人员审核),2,authed(审核通过,等待发货),3,shipped(已发货状态),4,completed(完成状态)。

当用户提交订单后,对订单的操作就有取消,审核,发货,完成等几个操作。假设要对订单进行取消操作,订单状态必须是created和authed状态。要对订单进行审核,订单状态必须是created,要发货,订单状态必须authed,要执行完成操作,订单必须是shipped状态, completed状态的订单,不能执行任何操作。

要执行这些操作,不用多态的情况下,我们的代码里会充斥着许多if else。如果业务逻辑再复杂些,代码中的if else条件会多得让你搞不清楚,或许你当时明白,但是过一两天你再来修改这段代码的时候,90%以上的情况你都需要花很长理一遍。如果是别人维护你的代码,再加上个人写代码的风格不同,别人就需要更长的时间来理解你的代码,这造成了维护成本过高的问题。

现在,假如我们做一个要对订单做一些操作,考虑先面代码:

getOrder($id); if ($order['status'] != 'created' || $order['status'] != 'authed') throw $this->createServiceException('Can\'t cancel order(id=' . $id . ')'); return $this->getOrderDao()->update($id, array('status' => 'cancel')); } public function authOrder($id) { $order = $this->getOrder($id); if ($order['status'] != 'created') throw $this->createServiceException('Can\'t auth order(id=' . $id . ')'); return $this->getOrderDao()->update($id, array('status' => 'authed')); } public function shippingOrder($id) { $order = $this->getOrder($id); if ($order['status'] != 'authed') throw $this->createServiceException('Can\'t shipping order(id=' . $id . ')'); return $this->getOrderDao()->update($id, array('status' => 'shipped')); } public function completeOrder($id) { $order = $this->getOrder($id); if ($order['status'] != 'shipped') throw $this->createServiceException('Can\'t complete order(id=' . $id . ')'); return $this->getOrderDao()->update($id, array('status' => 'completed')); } public function getOrder($id) { $order = $this->getOrderDao()->findOrder($id); if (empty($order)) throw $this->createServiceException('Order does not exist(id=' . $id . ')'); return $order; } }以上代码中,除getOrder方法外,结构相似,而且都有if else结构,因为写法的原因else并没有体现出来,如果义务逻辑复杂,会有更多的if else,甚至是if(){} elseif(){} elseif(){}else{}这种复杂的判断语句出现。现在我们开始使用多态。首先,订单有4个状态,created、authed、shipped和completed,依据这四个状态我们就可以抽象出四种类型的订单(就和人可以抽象成男人和女人一样),我们把依据四个状态抽象出来的订单叫做StatusOrder;现在我们定义一个接口:interface StatusOrder { //取消订单 public function cancelOrder(); //订单审核 public function authOrder(); //订单发货 public function shippingOrder(); //完成订单 public function completeOrder(); }现在我们来实现四种不状态的订单类:class BaseOrder { private $order; public function __construct($id) { $id = (int) $id; $order = $this->getOrderDao()->findOrder($id); if (empty($order)) throw new Exception('Order does not exist(id=' . $id . ')'); $this->order = $order; } public function getOrder() { return $this->order; } }// 刚创建的订单,可以执行取消和审核两个操作class CreatedOrder extends BaseOrder implements StatusOrder { public function cancelOrder() { $order = $this->getOrder(); return $this->getOrderDao()->update($order['id'], array('status' => 'cancel')); } public function authOrder() { $order = $this->getOrder(); return $this->getOrderDao()->update($id, array('status' => 'authed')); } public function shippingOrder() { $order = $this->getOrder(); throw new Exception('Can\'t shipping order(id=' . $order['id'] . ')'); } public function completeOrder($id) { $order = $this->getOrder(); throw new Exception('Can\'t complete order(id=' . $order['id'] . ')'); }}//已审核的订单,可以执行发货操作和取消操作class AuthedOrder extends BaseOrder implements StatusOrder { public function cancelOrder() { $order = $this->getOrder(); return $this->getOrderDao()->update($order['id'], array('status' => 'authed')); } public function authOrder() { $order = $this->getOrder(); throw new Exception('Can\'t auth order(id=' . $order['id'] . ')'); } public function shippingOrder() { $order = $this->getOrder(); return $this->getOrderDao()->update($order['id'], array('status' => 'shipped')); } public function completeOrder() { $order = $this->getOrder(); throw new Exception('Can\'t complete order(id=' . $order['id'] . ')'); }}//已发货的订单,可以执行完成操作class ShippedOrder extends BaseOrder implements StatusOrder { public function cancelOrder() { $order = $this->getOrder(); throw new Exception('Can\'t cancel order(id=' . $order['id'] . ')'); } public function authOrder() { $order = $this->getOrder(); throw new Exception('Can\'t auth order(id=' . $order['id'] . ')'); } public function shippingOrder() { $order = $this->getOrder(); throw new Exception('Can\'t shipping order(id=' . $order['id'] . ')'); } public function completeOrder() { $order = $this->getOrder(); return $this->getOrderDao()->update($order['id'], array('status' => 'completed')); }}//已完成的订单,什么操作都不能执行class CompleteOrder extends BaseOrder implements StatusOrder { public function cancelOrder($id) { $order = $this->getOrder(); throw new Exception('Can\'t cancel order(id=' . $order['id'] . ')'); } public function authOrder($id) { $order = $this->getOrder(); throw new Exception('Can\'t auth order(id=' . $order['id'] . ')'); } public function shippingOrder($id) { $order = $this->getOrder(); throw new Exception('Can\'t shipping order(id=' . $order['id'] . ')'); } public function completeOrder($id) { $order = $this->getOrder(); throw new Exception('Can\'t complete order(id=' . $order['id'] . ')'); }}现在,我们在Service层(业务逻辑层)去实现订单操作:class OrderServiceImpl extends BaseService implements OrderService{ // 获取某个状态订单类的一个实例,也可以使用一个工厂方法获取 private function getStatusOrder($id) { $order = $this->getOrderDao()->findOrder($id); //根据数据库字段获取类名,若取出的订单状态为created, 则$statusOrder值为CreatedOrder $statusOrder = ucfirst(strtolower($order['status'])).Order; return new $statusOrder; } public function cancelOrder($id) { //TODO:权限检查 return $this->getStatusOrder($id)->cancelOrder($id); } public function authOrder($id) { //TODO:权限检查 return $this->getStatusOrder($id)->authOrder($id); } public function shippingOrder($id) { return $this->getStatusOrder($id)->shippingOrder($id); } public function completeOrder($id) { return $this->getStatusOrder($id)->completeOrder($id); } }//客户端调用class OrderController { //取消订单 public function cancelAction($id) { //Other operation etc. try { $this->getOrderService()->cancelOrder($id); return 'success'; } catch (Exception $e){ return $e->getMessage(); } } public function shippingAction($id) { //Other operation etc. try { $this->getOrderService()->shippingOrder($id); return 'success'; } catch (Exception $e) { return $e->getMessage(); } } // etc. ........................................... }使用多态以后,代码变的简洁,消除了相同形式的代码和if语句。service层(业务逻辑层)执行操作的时候不在关心订单所处的状态,不需要判断。同时,如果我们的订单还要加入一个状态,比如审核未通过(authFailed),这时可以对审核未通过的订单做一些操作,如果按照原来的写发,我们还要去考虑原有代码当中的if else语句,例如:要求要审核未通过(authFailed)也可以被取消, 原来写法中的代码: public function cancelOrder($id) { $order = $this->getOrder($id); if ($order['status'] != 'created' || $order['status'] != 'authed') throw $this->createServiceException('Can\'t cancel order(id=' . $id . ')'); return $this->getOrderDao()->update($id, array('status' => 'cancel')); }

会变为

public function cancelOrder($id)    {        $order = $this->getOrder($id);        if ($order['status'] != 'created' || $order['status'] != 'authed' || $order['status'] != 'authFailed')            throw $this->createServiceException('Can\'t cancel order(id=' . $id . ')');        return $this->getOrderDao()->update($id, array('status' => 'cancel'));    }如果其他操作也涉及到审核失败这个状态,那我们还要修改其他代码。使用多态以后,我们添加一个类AuthFailed实现StatusOrder接口,其他代码基本不用修改,就可以实现功能增加,系统可维护性和可扩展性就大大提升。

转载于:https://my.oschina.net/centerLife/blog/122214

你可能感兴趣的文章
Android 小技巧-- TextView与EditText 同步显示
查看>>
苹果企业版帐号申请记录
查看>>
C++ Error: error LNK2019: unresolved external symbol
查看>>
Bitmap 和Drawable 的区别
查看>>
Java操作mongoDB2.6的常见API使用方法
查看>>
如何给服务器设置邮件警报。
查看>>
CEF js调用C#封装类含注释
查看>>
麦克劳林
查看>>
延时接通电路
查看>>
周爱民:真正的架构师是没有title的(图灵访谈)
查看>>
Eclipse SVN修改用户名和密码
查看>>
架构师的职责都有哪些?
查看>>
SVN: bdb: BDB1538 Program version 5.3 doesn't match environment version 4.7
查看>>
jsp内置对象作业3-application用户注册
查看>>
android115 自定义控件
查看>>
iOS uuchart 用法
查看>>
c# 多线程 调用带参数函数
查看>>
JQuery 如何选择带有多个class的元素
查看>>
The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar
查看>>
VS快速生成JSON数据格式对应的实体
查看>>