ThinkPHP 6.0 管道模式与中间件的实现分析
设计模式六大原则
- 开放封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
- 里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象.
- 依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
- 单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。
- 接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
- 迪米特法则:一个对象应该对其他对象保持最少的了解。
1.单例设计模式(Singleton)
所谓单例模式,即在应用程序中最多只有该类的一个实例存在,一旦创建,就会一直存在于内存中!
应用场景:
单例设计模式常应用于数据库类设计,采用单例模式,只连接一次数据库,防止打开多个数据库连接。
一个单例类应具备以下特点:
单例类不能直接实例化创建,而是只能由类本身实例化。因此,要获得这样的限制效果,构造函数必须标记为private,从而防止类被实例化。
需要一个私有静态成员变量来保存类实例和公开一个能访问到实例的公开静态方法。
在PHP中,为了防止他人对单例类实例克隆,通常还为其提供一个空的私有__clone()
方法。
单例模式的例子:
<?php /**
* Singleton of Database
*/
class Database
{
// We need a static private variable to store a Database instance.
privatestatic $instance; // Mark as private to prevent it from being instanced.
private function__construct()
{
// Do nothing.
} private function__clone()
{
// Do nothing.
} public static function getInstance()
{
if (!(self::$instance instanceof self)) {
self::$instance = new self();
} return self::$instance;
}
} $a =Database::getInstance();
$b =Database::getInstance(); // true
var_dump($a === $b);
2.工厂设计模式
要是当操作类的参数变化时,只用改相应的工厂类就可以
工厂设计模式常用于根据输入参数的不同或者应用程序配置的不同来创建一种专门用来实例化并返回其对应的类的实例。
使用场景:使用方法 new实例化类,每次实例化只需调用工厂类中的方法实例化即可。
优点:由于一个类可能会在很多地方被实例化。当类名或参数发生变化时,工厂模式可简单快捷的在工厂类下的方法中 一次性修改,避免了一个个的去修改实例化的对象。
我们举例子,假设矩形、圆都有同样的一个方法,那么我们用基类提供的API来创建实例时,通过传参数来自动创建对应的类的实例,他们都有获取周长和面积的功能。
例子
<?php interface InterfaceShape
{
function getArea();
function getCircumference();
} /**
* 矩形
*/
class Rectangle implements InterfaceShape
{
private $width;
private $height; public function __construct($width, $height)
{
$this->width = $width;
$this->height = $height;
} public function getArea()
{
return $this->width* $this->height;
} public function getCircumference()
{
return 2 * $this->width + 2 * $this->height;
}
} /**
* 圆形
*/
class Circle implements InterfaceShape
{
private $radius; function __construct($radius)
{
$this->radius = $radius;
} public function getArea()
{
return M_PI * pow($this->radius, 2);
} public function getCircumference()
{
return 2 * M_PI * $this->radius;
}
} /**
* 形状工厂类
*/
class FactoryShape
{
public static function create()
{
switch (func_num_args()) {
case1:
return newCircle(func_get_arg(0));
case2:
return newRectangle(func_get_arg(0), func_get_arg(1));
default:
# code...
break;
}
}
} $rect =FactoryShape::create(5, 5);
// object(Rectangle)#1 (2) { ["width":"Rectangle":private]=> int(5) ["height":"Rectangle":private]=> int(5) }
var_dump($rect);
echo "<br>"; // object(Circle)#2 (1) { ["radius":"Circle":private]=> int(4) }
$circle =FactoryShape::create(4);
var_dump($circle);
3.观察者设计模式
观察者模式是挺常见的一种设计模式,使用得当会给程序带来非常大的便利,使用得不当,会给后来人一种难以维护的想法。
- 很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的加群(点击→)677079770
使用场景:用户登录,需要写日志,送积分,参与活动 等使用消息队列,把用户和日志,积分,活动之间解耦合
什么是观察者模式?一个对象通过提供方法允许另一个对象即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。观察者模式是一种事件系统,意味着这一模式允许某个类观察另一个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作;观察者模式为您提供了避免组件之间紧密耦。看下面例子你就明白了!
<?php /*
观察者接口
*/
interface InterfaceObserver
{
function onListen($sender, $args);
function getObserverName();
} // 可被观察者接口
interface InterfaceObservable
{
function addObserver($observer);
function removeObserver($observer_name);
} // 观察者抽象类
abstract class Observer implements InterfaceObserver
{
protected $observer_name; function getObserverName()
{
return $this->observer_name;
} function onListen($sender, $args)
{ }
} // 可被观察类
abstract class Observable implements InterfaceObservable
{
protected $observers = array(); public function addObserver($observer)
{
if ($observerinstanceofInterfaceObserver)
{
$this->observers[] = $observer;
}
} public function removeObserver($observer_name)
{
foreach ($this->observersas $index => $observer)
{
if ($observer->getObserverName() === $observer_name)
{
array_splice($this->observers, $index, 1);
return;
}
}
}
} // 模拟一个可以被观察的类
class A extends Observable
{
public function addListener($listener)
{
foreach ($this->observersas $observer)
{
$observer->onListen($this, $listener);
}
}
} // 模拟一个观察者类
class B extends Observer
{
protected $observer_name = 'B'; public function onListen($sender, $args)
{
var_dump($sender);
echo "<br>";
var_dump($args);
echo "<br>";
}
} // 模拟另外一个观察者类
class C extends Observer
{
protected $observer_name = 'C'; public function onListen($sender, $args)
{
var_dump($sender);
echo "<br>";
var_dump($args);
echo "<br>";
}
} $a = new A();
// 注入观察者
$a->addObserver(new B());
$a->addObserver(new C()); // 可以看到观察到的信息
$a->addListener('D'); // 移除观察者
$a->removeObserver('B'); // 打印的信息:
// object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }
// string(1) "D"
// object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }
// string(1) "D"
4.适配器模式
将一个类的接口转换成客户希望的另一个接口,适配器模式使得原本的由于接口不兼容而不能一起工作的那些类可以一起工作。
应用场景:老代码接口不适应新的接口需求,或者代码很多很乱不便于继续修改,或者使用第三方类库。
例如:php连接数据库的方法:mysql,,mysqli,pdo,可以用适配器统一
//老的代码 class User { private $name; function __construct($name) { $this->name = $name; } public function getName() { return $this->name; } }
//新代码,开放平台标准接口 interface UserInterface { function getUserName(); } class UserInfo implements UserInterface { protected $user; function __construct($user) { $this->user = $user; } public function getUserName() { return $this->user->getName(); } }
$olduser = new User('张三'); echo $olduser->getName()."n"; $newuser = new UserInfo($olduser); echo $newuser->getUserName()."n";
5.策略模式
将一组特定的行为和算法封装成类,以适应某些特定的上下文环境。
使用场景:个人理解,策略模式是依赖注入,控制反转的基础
例如:一个电商网站系统,针对男性女性用户要各自跳转到不同的商品类目,并且所有广告位展示不同的广告
MaleUserStrategy.php
<?php namespace IMooc;
class MaleUserStrategy implements UserStrategy {
function showAd()
{
echo "IPhone6";
} function showCategory()
{
echo "电子产品";
}
}
FemaleUserStrategy.php
<?php namespace IMooc; class FemaleUserStrategy implements UserStrategy {
function showAd()
{
echo "2014新款女装";
}
function showCategory()
{
echo "女装";
}
}
UserStrategy.php
<?php namespace IMooc; interface UserStrategy {
function showAd();
function showCategory();
} <?php
interface FlyBehavior{
public function fly();
} class FlyWithWings implements FlyBehavior{
public function fly(){
echo "Fly With Wings \n";
}
} class FlyWithNo implements FlyBehavior{
public function fly(){
echo "Fly With No Wings \n";
}
}
class Duck{
private $_flyBehavior;
public function performFly(){
$this->_flyBehavior->fly();
} public function setFlyBehavior(FlyBehavior $behavior){
$this->_flyBehavior = $behavior;
}
} class RubberDuck extends Duck{
}
// Test Case
$duck = new RubberDuck(); /* 想让鸭子用翅膀飞行 */
$duck->setFlyBehavior(new FlyWithWings());
$duck->performFly(); /* 想让鸭子不用翅膀飞行 */
$duck->setFlyBehavior(new FlyWithNo());
$duck->performFly();
6.装饰器模式
使用场景:当某一功能或方法draw,要满足不同的功能需求时,可以使用装饰器模式;实现方式:在方法的类中建addDecorator(添加装饰器),beforeDraw,afterDraw 3个新方法, 后2个分别放置在要修改的方法draw首尾.然后创建不同的装器类(其中要包含相同的,beforeDraw,afterDraw方法)能过addDecorator添加进去,然后在beforeDraw,afterDraw中循环处理,与观察者模式使用有点相似
1.装饰器模式(Decorator),可以动态地添加修改类的功能
2.一个类提供了一项功能,如果要在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重新实现类的方法
3.使用装饰器模式,仅需在运行时添加一个装饰器对象即可实现,可以实现最大的灵活性
DrawDecorator.php
<?php
namespace IMooc; interface DrawDecorator
{
function beforeDraw();
function afterDraw();
}
Canvas.php
<?php
namespace IMooc; class Canvas
{
public $data;
protected $decorators = array(); //Decorator
function init($width = 20, $height = 10)
{
$data = array();
for($i = 0; $i < $height; $i++)
{
for($j = 0; $j < $width; $j++)
{
$data[$i][$j] = '*';
}
}
$this->data = $data;
} function addDecorator(DrawDecorator $decorator)
{
$this->decorators[] = $decorator;
} function beforeDraw()
{
foreach($this->decorators as $decorator)
{
$decorator->beforeDraw();
}
} function afterDraw()
{
$decorators = array_reverse($this->decorators);
foreach($decorators as $decorator)
{
$decorator->afterDraw();
}
} function draw()
{
$this->beforeDraw();
foreach($this->data as $line)
{
foreach($line as $char)
{
echo $char;
}
echo "<br />\n";
}
$this->afterDraw();
} function rect($a1, $a2, $b1, $b2)
{
foreach($this->data as $k1 => $line)
{
if ($k1 < $a1 or $k1 > $a2) continue;
foreach($line as $k2 => $char)
{
if ($k2 < $b1 or $k2 > $b2) continue;
$this->data[$k1][$k2] = ' ';
}
}
}
}
ColorDrawDecorator.php
<?php
namespace IMooc; class ColorDrawDecorator implements DrawDecorator
{
protected $color;
function __construct($color = 'red')
{
$this->color = $color;
}
function beforeDraw()
{
echo "<div style='color: {$this->color};'>";
}
function afterDraw()
{
echo "</div>";
}
}
index.php
<?php
define('BASEDIR', __DIR__);
include BASEDIR.'/IMooc/Loader.php';
spl_autoload_register('\\IMooc\\Loader::autoload'); $canvas = new IMooc\Canvas();
$canvas->init();
$canvas->addDecorator(new \IMooc\ColorDrawDecorator('green'));
$canvas->rect(,,,);
$canvas->draw();
ThinkPHP 6.0 管道模式与中间件的实现分析的更多相关文章
- Windows Azure Cloud Service (41) 修改云服务IIS托管管道模式为4.0经典模式
<Windows Azure Platform 系列文章目录> 这是笔者在之前的项目中遇到的问题,做一下总结,给网友做参考. 在一般情况下,Visual Studio开发的Cloud Se ...
- ISAPI和CGI限制中没有ASP.NET v4.0 ; vS2013检测到在集成的托管管道模式下不适用的 ASP.NET 设置。
统确实自带了ASP.NET v4.0,但是ISAPI中没有这个选项,导致服务器开不起来 解决方法如下: 1.确保安装IIS时确实安装了ASP.NET,如果没有的话,勾上重新装一下,一般出现404.2时 ...
- 【配置】检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法(非简单设置为【经典】模式)。
× 检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法(非简单设置为[经典]模式). 我们将ASP.NET程序从IIS6移植到IIS7,可能运行提示以下错误: HTTP 错误 5 ...
- HTTP 错误 500.23 - Internal Server Error 检测到在集成的托管管道模式下不适用的 ASP.NET 设置。
检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法(非简单设置为[经典]模式). - CatcherX 2014-03-11 11:03 27628人阅读 评论(2) 收藏 举报 分类 ...
- IIS 7 托管管道模式 经典模式(Classic) 集成模式(Integrated) 分析与理解
IIS 7.0 支持两种管道模式:一种是IIS 7.0最新提供的集成管道模式,另一种是经典管道模式,经典管道模式是由先前版本的IIS提供的. 我们可以通过应用程序池设置管道模式,这项功能对IIS管理员 ...
- IIS 之 托管管道模式
IIS 7.0 支持两种管道模式: (1)IIS 7.0 最新提供的集成管道模式(Integrated), (2)经典管道模式(Classic),经典管道模式是由先前版本的IIS提供的. 我们可以通过 ...
- SQL Server(解决问题)已成功与服务器建立连接,但是在登录过程中发生错误。(provider: Shared Memory Provider, error:0 - 管道的另一端上无任何进程。
http://blog.csdn.net/github_35160620/article/details/52676416 如果你在使用新创建的 SQL Server 用户名和密码 对数据库进行连接的 ...
- ThinkPHP 5.0/5.1 自定义404界面的配置
★ 背景还要啥背景,就是觉得不可能用框架自带的 404 界面呗.可能跟之前的版本配置方法有点区别,在此做一下简单的笔记 框架:ThinkPHP 5.1,ThinkPHP5.0.20 ★ 配置过程♩. ...
- 【ASP.NET 问题】IIS发布网站后出现“检测到在集成的托管管道模式下不适用的ASP.NET设置”的解决办法
系统环境:win7 asp.net4.0网站挂到本地IIS上报错: google一下,发现N页解决方案,但是点进去一看前篇一律的解决方法是.将IIS7 下网站托管管道由继承模式修改为经典模式,这其实是 ...
随机推荐
- Scanner接收字符
char num = input.next().charAt(0); //截取指定位置的字符,下标从0开始 System.out.println("helloworld".char ...
- Yroot of High-Precisions (luogu P2293 [HNOI2004]高精度开根)
Background\text{Background}Background I've accepted\text{I've accepted}I've accepteda very good prob ...
- Flink整合oozie shell Action 提交任务 带kerberos认证
最近这段时间一直在忙新集群迁移,上了最新的cdh6.3.0 于是Flink 提交遇到了许多的问题 还好有cloudera License 有了原厂的帮助和社区的伙伴,问题解决起来快了不少,手动滑稽 集 ...
- 10.Linux用户权限
1.权限基本概述 1. 什么是权限? 我们可以把它理解为操作系统对用户能够执行的功能所设立的限制,主要用于约束用户能对系统所做的操作,以及内容访问的范围,或者说,权限是指某个特定的用户具有特定的系统资 ...
- fullpage.js的引入方法
1.先到官网上(https://github.com/alvarotrigo/fullPage.js)下载压缩包 2.引入文件 3.布局基本页面结构 4.实现全屏滚动(JS代码) <script ...
- Python 命令行之旅:使用 docopt 实现 git 命令
作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...
- Java多线程编程(四)Lock的使用
一.使用ReentrantLock类 在Java多线程中,可以使用synchronized关键字来实现线程之间的同步互斥,但ReentrantLock类也能达到同样的效果,并且在扩展功能上也更加强大, ...
- vue路由安装
1.安装路由: vue ui cnpm install vue-router 2.使用,导入: 默认创建项目的时候就已经帮你写好了. import router from "vue-rout ...
- TensorFlow初学教程(完整版)
1:你想要学习TensorFlow,首先你得安装Tensorflow,在你学习的时候你最好懂以下的知识: a:怎么用python编程: b:了解一些关于数组的知识: c:最理想的 ...
- 热门开源网关的性能对比:Goku > Kong > Tyk
不多说,先展示最后的性能测试结果 我们将Goku与市场上的其他同类热门产品进行比较,使用相同的环境和条件,测试以下产品:Goku.Kong.Tyk.简单介绍下, Goku API Gateway (中 ...