工厂模式的实现

<?php
declare(strict_types=1);
ini_set('display_errors', 'On');
error_reporting(-1);

/**
 * Product接口
 */
interface Product
{
    public function operation(): void;
}

/**
 * ProductA类(实现Product接口)
 */
class ProductA implements Product
{
    public function operation(): void
    {
        echo 'Product A operation' . PHP_EOL;
    }
}

/**
 * ProductB类(实现Product接口)
 */
class ProductB implements Product
{
    public function operation(): void
    {
        echo 'Product B operation' . PHP_EOL;
    }
}

/**
 * 工厂类
 */
class Factory
{
    /**
     * 创建产品
     *
     * @param string $productType 产品类型,可选值:A | B
     * @return ProductA|ProductB ProductA对象或ProductB对象
     */
    public static function createProduct(string $productType): ProductA|ProductB
    {
        if ($productType === 'A') {
            return new ProductA(); // 创建ProductA对象
        }

        if ($productType === 'B') {
            return new ProductB(); // 创建ProductB对象
        }

        throw new UnexpectedValueException();
    }
}

// 利用工厂类创建产品对象
Factory::createProduct('A')->operation(); // Product A operation
Factory::createProduct('B')->operation(); // Product B operation

/**
 * 创建产品
 *
 * @param string $productType 产品类型,可选值:A | B
 * @return ProductA|ProductB ProductA对象或ProductB对象
 */
function create_product(string $productType): ProductA|ProductB
{
    $class = "Product$productType"; // 类名,示例:ProductA、ProductB

    if (class_exists($class)) {
        return new $class(); // 通过可变变量创建ProductA对象或ProductB对象
    }

    throw new UnexpectedValueException();
}

// 利用可变变量创建产品对象
create_product('A')->operation(); // Product A operation
create_product('B')->operation(); // Product B operation


//========== 总结 ==========//
// 1、工厂模式的本质其实就是把类名作为参数调用Factory::createProduct()方法,然后该方法返回指定类名的对象。
// 2、在PHP中,还可以通过可变变量变相实现工厂模式,而且这种方式比标准的工厂模式更加简单灵活。
// 3、工厂模式主要作用之一是屏蔽工厂产品的底层实现细节,让客户端(即方法调用方)只专注于使用工厂产品实现自身业务。
//    以缓存功能为例,底层可以基于File、APCu、Memcached、Redis等各种方式实现,而对于客户端来说,只要指定使用上述哪种缓存方式,
//    然后调用Product::set()、Product::get()、Product::del()等方法操作缓存即可,至于是如何基于指定缓存方式实现这些方法的,
//    客户端无需知道,客户端只要知道set()可以设置缓存、get()可以获取缓存、del()可以删除缓存就行了。

Copyright © 2024 码农人生. All Rights Reserved