Solar工厂模式/工厂方法

SOLAR PHP 群中有人要求我写一篇介绍如何开发Solar插件的文章,恩,我也觉得很有必要,不过要介绍Solar插件,我认为必须先介绍Solar工厂模式和Solar依赖注入才能更好的了解Solar插件。那么这篇文章就来介绍下Solar的工厂模式。

首先来看下Solar工厂方法,对于一个框架来说工厂函数至关重要,所以该方法在Solar架构类中,点击这里查看,由此可见其重要性。

    public static function factory($class, $config = null)
{
    Solar_Class::autoload($class);
    $obj = new $class($config);
    // is it an object factory?
    if ($obj instanceof Solar_Factory) {
        // return an instance from the object factory
        return $obj->factory();
    }
    // return the object itself
    return $obj;
}

大致意思如下:

首先通过Solar\_Class::autoload()方法加载文件,该方法会在被PHP或SOLAR包含过的所有路径中查找类文件。 然后实例化类,如果该对象是Solar\_Factory的实例,则直接调用对象的factory方法,并返回结果。如果不是则直接返回对象。

代码很简单,但设计得很巧妙。妙就妙在Solar\_Factory类,它是一个抽象类,不能直接实例化它。适配器模式主要就是由它实现的。请看factory方法:

    public function factory()
{
    // bring in the config and get the adapter class.
    $config = $this->_config;
    $class = $config['adapter'];
    unset($config['adapter']);

    // return the factoried adapter object
    return new $class($config);
}

在实例化Solar\_Factory类型的对象时,接收的数组参数中一般都有'adapter'项,如:

    array(
    'adapter' => 'Solar_Foo',
    // ... more
    // ,
)

该选项告诉工厂函数要真正实例化的类,数组参数中的其他项将会被传递给真正需要实例化的类,在上面代码中,Solar\_Foo是我们真正要实例化的类。

这个有什么用呢?呵呵,当然有用了,举个例子吧:

现在你要写个支付模块,我们都知道支付手段不只一种(常见的有,支付宝、财付通、百付宝、网银在线等)。我们希望增加或删除任何一种支付手段无需修改支付模块代码。如果是这样你会怎么设计呢?

我们要做的就是遵从Solar\_Factory的设计,如下:

| - /source/solar/Solar
 | - Pay.php (class Solar_Pay)
 | - Pay
      | - Adapter.php
      | - Adapter
           | - Alipay.php (class Solar_Pay_Adapter_Alipay)
           | - Alipay
           | - Tenpay.php (class Solar_Pay_Adapter_Tenpay)
           | - Tenpay
           | - ...

简单写下代码吧,:)

    # /source/solar/Solar/Pay.php
class Solar_Pay extends Solar_Factory
{
    $_Solar_Pay = array(
        'adapter' => 'Solar_Pay_Adapter_Alipay',
    );
    // ...
}

# /source/solar/Solar/Pay/Adapter.php
class Solar_Pay_Adapter extends Solar_Base
{
    // ...
}

# /source/solar/Solar/Pay/Adapter/Alipay.php
class Solar_Pay_Adapter_Alipay extends Solar_Pay_Adapter
{
    // ...
}

# call
$params = array('Adapter' => 'Solar_Pay_Adapter_Alipay',
                'partner' => '...',
                'security_code' => '...',
                'seller_email' => 'your@email.com',
                'show_url' => '...',
                'notify_url' => '...',
                'return_url' => '...',
);
// call alipay
$alipay = Solar::factory('Solar_Pay', $params);