设计模式六大原则

  • 开放封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
  • 里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象.
  • 依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
  • 单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。
  • 接口隔离原则:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
  • 迪米特法则:一个对象应该对其他对象保持最少的了解。

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 管道模式与中间件的实现分析的更多相关文章

  1. Windows Azure Cloud Service (41) 修改云服务IIS托管管道模式为4.0经典模式

    <Windows Azure Platform 系列文章目录> 这是笔者在之前的项目中遇到的问题,做一下总结,给网友做参考. 在一般情况下,Visual Studio开发的Cloud Se ...

  2. ISAPI和CGI限制中没有ASP.NET v4.0 ; vS2013检测到在集成的托管管道模式下不适用的 ASP.NET 设置。

    统确实自带了ASP.NET v4.0,但是ISAPI中没有这个选项,导致服务器开不起来 解决方法如下: 1.确保安装IIS时确实安装了ASP.NET,如果没有的话,勾上重新装一下,一般出现404.2时 ...

  3. 【配置】检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法(非简单设置为【经典】模式)。

      ×   检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法(非简单设置为[经典]模式). 我们将ASP.NET程序从IIS6移植到IIS7,可能运行提示以下错误: HTTP 错误 5 ...

  4. HTTP 错误 500.23 - Internal Server Error 检测到在集成的托管管道模式下不适用的 ASP.NET 设置。

    检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法(非简单设置为[经典]模式). - CatcherX 2014-03-11 11:03 27628人阅读 评论(2) 收藏 举报  分类 ...

  5. IIS 7 托管管道模式 经典模式(Classic) 集成模式(Integrated) 分析与理解

    IIS 7.0 支持两种管道模式:一种是IIS 7.0最新提供的集成管道模式,另一种是经典管道模式,经典管道模式是由先前版本的IIS提供的. 我们可以通过应用程序池设置管道模式,这项功能对IIS管理员 ...

  6. IIS 之 托管管道模式

    IIS 7.0 支持两种管道模式: (1)IIS 7.0 最新提供的集成管道模式(Integrated), (2)经典管道模式(Classic),经典管道模式是由先前版本的IIS提供的. 我们可以通过 ...

  7. SQL Server(解决问题)已成功与服务器建立连接,但是在登录过程中发生错误。(provider: Shared Memory Provider, error:0 - 管道的另一端上无任何进程。

    http://blog.csdn.net/github_35160620/article/details/52676416 如果你在使用新创建的 SQL Server 用户名和密码 对数据库进行连接的 ...

  8. ThinkPHP 5.0/5.1 自定义404界面的配置

    ★ 背景还要啥背景,就是觉得不可能用框架自带的 404 界面呗.可能跟之前的版本配置方法有点区别,在此做一下简单的笔记 框架:ThinkPHP 5.1,ThinkPHP5.0.20 ★ 配置过程♩. ...

  9. 【ASP.NET 问题】IIS发布网站后出现“检测到在集成的托管管道模式下不适用的ASP.NET设置”的解决办法

    系统环境:win7 asp.net4.0网站挂到本地IIS上报错: google一下,发现N页解决方案,但是点进去一看前篇一律的解决方法是.将IIS7 下网站托管管道由继承模式修改为经典模式,这其实是 ...

随机推荐

  1. QT文件读写操作笔记

    补一下这部分的笔记 简单的东西也记一下 操作系统一般都会提供一些列的标准对话框,如文件选择.字体选择.颜色选择等,这些标准对话框为应用层序提供了一致的观感.Qt对这些标准对话框都定义了相关的类,如:Q ...

  2. 2019.4.22 python_Flag

    想了很久  最后觉得还是对编程的知识点好好重新的拉一边 回炉重造并不可笑 虽然从C到java到php到python 有两年的时间了 但是很多知识点都是零零碎碎,没有花时间复习和记录 所以决定从pyth ...

  3. php的cookie怎么使用

    PHP中Cookie的使用---添加/更新/删除/获取Cookie 及 自动填写该用户的用户名和密码和判断是否第一次登陆 什么是cookie? 服务器在客户端保存用户的信息,比如登录名,密码等. 这些 ...

  4. js转换页面为图片并下载

    <div style="background:red;width: 600px;height: 600px;" class="test"> < ...

  5. 百万年薪python之路 -- 迭代器

    3.1 可迭代对象 3.1.1 可迭代对象定义 **在python中,但凡内部含有 _ _ iter_ _方法的对象,都是可迭代对象**. 3.1.2 查看对象内部方法 该对象内部含有什么方法除了看源 ...

  6. C++两个队列实现一个栈

    C++两个队列实现一个栈 /* * source.cpp * * Created on: 2015年6月21日 * Author: codekiller */ #include "iostr ...

  7. GO基础之数组

    一.数组的声明与遍历 package main import "fmt" //声明数组的形式1 ]int ], , , } func main() { // 声明数组的形式2 a ...

  8. Java基础(三)对象与类

    1.类的概念:类是构造对象的模板或蓝图.由类构造对象的过程称为创建类的实例. 2.封装的概念:封装(有时称为数据隐藏)是与对象有关的一个重要概念.对象中的数据称为实例域,操纵数据的过程称为方法.对于每 ...

  9. expect实现自动输入密码功能

    系统: Ubuntu:16.04 安装expect: sudo apt-get update sudo apt-get install expect 脚本实例: //这一行告诉操作系统脚本里的代码使用 ...

  10. 小白学 Python(14):基础数据结构(集合)(上)

    人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...