对多态的理解(基于PHP)

本文探讨如何通过多态编程技术简化订单状态操作的代码逻辑,减少冗余的if-else判断,提高代码可读性和可维护性。具体介绍了如何将订单状态抽象为不同类,进而实现对不同类型订单的操作,有效提升系统的灵活性和扩展性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

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

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

<!-- lang: php -->
<?php 
//订单服务接口
interface OrderService {
    //取消订单
    public function cancelOrder($id);
    //订单审核
    public function authOrder($id);
    //订单发货
    public function shippingOrder($id);
    //完成订单
    public function completeOrder($id);
}

class OrderServiceImpl extends BaseService implements OrderService {
    
    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 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值