摸鱼时刻 - 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 协议》,转载必须注明作者和本文链接