摸鱼时刻 - 5分钟玩耍设计模式(2)

一、观察者模式(Observer)

尝试简单实现一下事件监听机制,模拟用户注册成功后触发事件~

1. BaseEvent 类

<?php

namespace App\Support;

abstract class BaseEvent
{
    private BaseEvent $event;

    public function __construct(BaseEvent $event)
    {
        $this->event = $event;
    }

    // 维护订阅列表
    private $listeners = [];

    public function addListener(BaseListener $listener)
    {
        array_push($this->listeners, $listener);
    }

    public function publish()
    {
        foreach ($this->listeners as $listener) {
            $listener->handle($this->event);
        }
    }
}

2. BaseListener 类

<?php

namespace App\Support;

abstract class BaseListener
{
    public abstract function handle(BaseEvent $event);

    public function subscribe(BaseEvent $event)
    {
        $event->addListener($this);
    }
}

3. User 用户模型

<?php

namespace App\Model;

class User
{
    public $name;
    public $age;

    public static function create($name, $age)
    {
        $user = new User();
        $user->name = $name;
        $user->age = $age;

        return $user;
    }
}

4. RegisterSuccessEvent 事件类

<?php

namespace App\Event;

use App\Model\User;
use App\Support\BaseEvent;

class RegisterSuccessEvent extends BaseEvent
{
    public $user;

    public function __construct(User $user)
    {
        $this->user = $user;

        parent::__construct($this);
    }
}

5. 简单来两个监听器

<?php

namespace App\Listener;

use App\Support\BaseEvent;
use App\Support\BaseListener;

class SendSmsListener extends BaseListener
{
    public function handle(BaseEvent $event)
    {
        $user = json_encode($event->user);
        echo "==== send sms: {$user}\n";
    }
}
<?php

namespace App\Listener;

use App\Support\BaseEvent;
use App\Support\BaseListener;

class SendPointsListener extends BaseListener
{
    public function handle(BaseEvent $event)
    {
        $user = json_encode($event->user);
        echo "==== send points: {$user}\n";
    }
}

6. 看看效果

<?php

class App
{
    public function run()
    {
        $user = User::create("kangkang", 18);

        $event = new RegisterSuccessEvent($user);

        $listener1 = new SendSmsListener();
        $listener1->subscribe($event);

        $listener2 = new SendPointsListener();
        $listener2->subscribe($event);

        $event->publish();

        // output:
        // ==== send sms: {"name":"kangkang","age":18}
        // ==== send points: {"name":"kangkang","age":18}
    }
}

二、策略模式(Strategy) + 工厂模式(Factory)

实现下对象实例化策略~

1. InstanceStrategy 策略接口

<?php

namespace App\Support;

interface InstanceStrategy
{
    public static function getInstance($class);
}

2. SingletonStrategy 单例策略

<?php

namespace App\Support;

class SingletonStrategy implements InstanceStrategy
{
    private static $instances = [];

    public static function getInstance($class)
    {
        if (isset(self::$instances[$class])) {
            return self::$instances[$class];
        }

        $obj = new $class();
        self::$instances[$class] = $obj;
        return $obj;
    }
}

3. PrototypeStrategy 原型策略

<?php

namespace App\Support;

class PrototypeStrategy implements InstanceStrategy
{
    public static function getInstance($class) 
    {
        return new $class();
    }
}

4. 来个工厂

<?php

namespace App\Constant;

class AppConstant
{
    public const SINGLETON = 1;

    public const PROTOTYPE = 2;
}
<?php

namespace App\Factory;

use App\Constant\AppConstant;
use App\Support\PrototypeStrategy;
use App\Support\SingletonStrategy;

class InstanceFactory
{
    private static $strategyMap = [
        AppConstant::SINGLETON => SingletonStrategy::class,
        AppConstant::PROTOTYPE => PrototypeStrategy::class,
    ];

    public static function getStrategy($strategy)
    {
        if (!isset(static::$strategyMap[$strategy])) {
            throw new \Exception("error strategy");
        }

        return self::$strategyMap[$strategy];
    }
}

5. Container 类,组合策略 + 工厂

<?php

namespace App\Support;

use App\Factory\InstanceFactory;

class Container
{
    public function make($class, $strategy)
    {
        return InstanceFactory::getStrategy($strategy)::getInstance($class);
    }
}

6. 看看效果

<?php

class App
{
    public function run()
    {
        $container = new Container();
        $user = $container->make(User::class, AppConstant::SINGLETON);
        echo json_encode($user) . "\n";

        // output:
        // {"name":null,"age":null}
    }
}

end~

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!