PHP常用设计模式详解

单例模式:

php交流群:159789818

特性:单例类只能有一个实例

  1. 类内__construct构造函数私有化,防止new实例
  2. 类内__clone私有化,防止复制对象
  3. 设置一个$instance私有静态属性,为了保存当前类的实例
  4. 设置一个getInstance公有方法,为了获取当前类的实例
  5. 减少new对象操作,合理使用内存

通常使用在获取某个全局配置项,或者数据库连接、操作等类上

Demo:

 <?php
Class Demo{
//用于保存当前类的实例
private static $instance;
//构造函数私有化,防止直接new当前对象
private function __construct(){}
//析构函数私有化,防止从外部直接复制当前对象
private function __clone(){}
//getInstance公有函数用于获取当前类的实例
public static function getInstance()
{
//判断当前类成员变量instance是否为空
//如果不为空,则直接返回类的实例
//如果为空,则new一个当前类的实例,并保存到类成员变量
//instance中,然后直接返回成员变量
if(empty(self::$instance))
{
//将实例保存到instance成员变量中
self::$instance = new static();
//直接返回成员变量
return self::$instance;
}else{
//直接返回类实例
return self::$instance;
}
}
}
$demo1 = Demo::getInstance();//获取到实例
$demo2 = new Demo();//报错

工厂模式(Factory Design Pattern)

特性:

  1. 降低系统耦合度
  2. 遵循开发-封闭原则 对修改封闭, 对扩展开放
  3. 通过工厂创建类的实例,而不是直接操作new关键字创建类的实例
  4. 已经使用的类内部发生改变,哪不需要在所有的地方都改变,只需要在类工厂类里改变既可
  5. 例如,支付宝微信银行等对接就可以写个工厂模式来对接

抽象工厂Demo:

<?php
//PaymentFactory.php
interface PaymentFactory
{
//请求收款码
public function QRcode();
//监听收款
public function Listen();
}
interface createPay { //将对象的创建抽象成一个接口
function createOpen($class,$data);//内向创建
function createIntro($class,$data);//外向创建
}
//微信支付类
Class WxPay implements PayMentFactory
{
public function QRcode()
{
//微信业务逻辑代码
//返回收款码以及订单相关参数
return "我是微信二维码";
}
public function Listen()
{
//微信业务逻辑代码
//返回订单结果
return "正在监听";
}
}
//阿里支付类
Class aliyun implements PayMentFactory
{
public function QRcode()
{
//业务逻辑代码
//返回收款码以及订单相关参数
return "我是支付宝二维码";
}
public function Listen()
{
//业务逻辑代码
//返回订单结果
return "正在监听";
}
}
//实现createPay接口
class CreateP implements createPay
{
public function createOpen($class,$data =[])
{
return new $class($data);
}
public function createIntro($class,$data = [])
{
return new $class($data);
}
}
//开发者类
class Client{
static function Get($class,$data = [])
{
$fac = new CreateP();
// var_dump($fac);
return $fac->createOpen($class,$data);
}
}
$pay = Client::Get("WxPay");
echo $pay->QRcode(); //输出,我是微信二维码

注册模式 Register

特性:

  1. 解决全局共享和交换对象
  2. 创建好的对象,挂到某个全局数组上
  3. 需要的时候直接去该数组上获取即可
  4. 将对象实例注册到全局树上

Demo:

<?php
//全局注册类
Class Register
{
//存储类的实例
public static $maps;
//注册操作
public static function Set($name,$cla)
{
//判断是否已经存储
if(array_key_exists($name,self::$maps))
{
//如果全局maps内已有则直接返回
return true;
}else{
//如果没有name 则将实例和name按键值对存储到成员变量内
self::$maps[$name] = $cla;
return true;
}
}
//获取类实例
public static function Get($name)
{
//判断name值是否存在
if(array_key_exists($name,self::$maps))
{
//如果存在则直接返回对应的类的实例
return self::$maps[$name];
}else{
//如果不存在,则返回false或者其他
return false;
}
}
}

适配器模式 Adapter :

特性:

  1. 将各种不同的函数接口封装到统一的api
  2. 降低因为接口底层代码的不同,而导致的调用?(个人理解)

Demo(网上直接copy来的):

接口 IDatabase
<?php
namespace IMooc;
interface IDatabase
{
function connect($host, $user, $passwd, $dbname);
function query($sql);
function close();
}
MySQL
<?php
namespace IMooc\Database;
use IMooc\IDatabase;
class MySQL implements IDatabase
{
protected $conn;
function connect($host, $user, $passwd, $dbname)
{
$conn = mysql_connect($host, $user, $passwd);
mysql_select_db($dbname, $conn);
$this->conn = $conn;
} function query($sql)
{
$res = mysql_query($sql, $this->conn);
return $res;
} function close()
{
mysql_close($this->conn);
}
}
MySQLi
<?php
namespace IMooc\Database;
use IMooc\IDatabase;
class MySQLi implements IDatabase
{
protected $conn; function connect($host, $user, $passwd, $dbname)
{
$conn = mysqli_connect($host, $user, $passwd, $dbname);
$this->conn = $conn;
} function query($sql)
{
return mysqli_query($this->conn, $sql);
} function close()
{
mysqli_close($this->conn);
}
}
PDO
<?php
namespace IMooc\Database;
use IMooc\IDatabase;
class PDO implements IDatabase
{
protected $conn;
function connect($host, $user, $passwd, $dbname)
{
$conn = new \PDO("mysql:host=$host;dbname=$dbname", $user, $passwd);
$this->conn = $conn;
}
function query($sql)
{
return $this->conn->query($sql);
} function close()
{
unset($this->conn);
}
}

通过以上案例,PHP与MySQL的数据库交互有三套API,在不同的场景下可能使用不同的API,那么开发好的代码,换一个环境,可能就要改变它的数据库API,那么就要改写所有的代码,使用适配器模式之后,就可以使用统一的API去屏蔽底层的API差异带来的环境改变之后需要改写代码的问题

观察者模式

特性:

  1. 观察者模式(Observer),当一个对象状态发生变化时,依赖它的对象全部会收到通知,并自动更新
  2. 一个事件发生后,要执行一连串更新操作。传统的编程思想,就是在这个事件的代码后直接加入处理的逻辑。当更新的逻辑增多之后,代码会变得难以维护。这种方式是耦合的,侵入式的,增加新的逻辑需要修改事件的主体代码。
  3. 观察者模式实现了低耦合,非侵入式的通知与更新机制

Demo:

<?php
//EventGenerator
//事件触发抽象类
abstract class EvemtGenerator
{
//存储观察者类
private $observer =[];
//添加观察者操作
public function AddOb(Observer $observer)
{
$this->observer[] = $observer;
}
//观察者通知操作
public function notify()
{
//循环类成员变量,并执行对应的观察者更新方法
foreach ($this->observer as $observer)
{
//执行每个观察者类内的更新操作
$observer->update();
}
}
}
//定义观察者接口
interface Observer
{
public function update();
} //实现一个被观察者类
Class Test extends EvemtGenerator
{
//实现一个登陆方法
public function login()
{
return "登陆成功";
}
}
//实现一个观察者
Class Observer1 implements Observer
{
//定义一个逻辑更新操作 例如:添加了csrf验证
public function update()
{
if($_POST['csrf'] == getCsrf())
{
return true;
}else{
exit("csrf验证不正确");
}
}
}
//实例化Test类 被观察
$event = new Test();
$event->AddOb(new Observer1());
$event->login();
//更新通知操作
$event->notify();

策略模式:

特性:

  1. 将一组特定的行为和算法封装成类,以适应某些特定的上下文环境
  2. 方便系统维护,例如:为每一个用户登陆时展现不同的页面
  3. 解耦

Demo:

//定义策略接口,规范策略行为
interface UserStrategy
{
public function show();
public function message();
}
//定义一个喜欢买西装的用户类
Class SuitUser implements UserStrategy
{
public function show()
{
//为用户跳转到西装页面
return "跳转到西装页面";
}
public function message()
{
//发送message
echo "即将为您展示最新的西装某某某";
}
}
//定义一个喜欢买裙子的用户类
Class skirtUser implements UserStrategy
{
public function show()
{
//为用户跳转到西装页面
return "跳转到裙子推荐页面";
}
public function message()
{
//发送message
echo "即将为您展示最新的裙子某某某";
}
}
//定义一个业务类
Class Users
{
//存储对应的用户类
private $userCla;
//执行策略接口
public function Start()
{
echo "跳转页面是:".$this->strategy->show();
echo "消息是:".$this->strategy->message();
}
//注册对应的用户类
public function SetStrategy(UserStrategy $strategy)
{
$this->$userCla = $strategy;
}
}
//业务逻辑代码 判断用户习性
$user1 = "西装";
$user2 = "裙子";
$userL = new Users();
//如果用户习性为喜欢看西装或者买西装则
if ($user1 == "西装"){
$userL->SetStrategy(new SuitUser());
$userL->Start();
}

PHP常用设计模式,PHP常用设计模式详解,PHP详解设计模式,PHP设计模式的更多相关文章

  1. spring(二、bean生命周期、用到的设计模式、常用注解)

    spring(二.bean生命周期.用到的设计模式.常用注解) Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的. ...

  2. python设计模式之常用创建模式总结(二)

    前言 设计模式的创建模式终极目标是如何使用最少量最少需要修改的代码,传递最少的参数,消耗系统最少的资源创建可用的类的实例对象. 系列文章 python设计模式之单例模式(一) python设计模式之常 ...

  3. Java基础-Java中23种设计模式之常用的设计模式

    Java基础-Java中23种设计模式之常用的设计模式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.设计模式分类 设计模式是针对特定场景给出的专家级的解决方案.总的来说设 ...

  4. linux tar命令 压缩、打包、解压 详解

    linux tar命令 压缩.打包.解压 详解 1.常用压缩命令 tar –czvf 压缩后的文件.tar.gz 要压缩的文件 2.常用解压命令 tar –xzvf 解压后的文件.tar.gz [要解 ...

  5. Android 6.0 RK3288 ROM编译详解+命令详解【转】

    本文转载自:http://blog.csdn.net/MLQ8087/article/details/58607692 Android 6.0 RK3288 ROM编译详解+命令详解 原创 2017年 ...

  6. Linux常用命令(常用)

    一,Linux常用命令二,CentOS没有盘符,只有根目录/,可以理解为只有一个盘有一个文件夹有点特殊,画了一个房子,代表当前用户的家 1.记住一个点:区分根目录和当前用户的家cd ~ 代表回家cd ...

  7. 总结js常用函数和常用技巧(持续更新)

    学习和工作的过程中总结的干货,包括常用函数.常用js技巧.常用正则表达式.git笔记等.为刚接触前端的童鞋们提供一个简单的查询的途径,也以此来缅怀我的前端学习之路. PS:此文档,我会持续更新. Aj ...

  8. eclipse 常用设置,常用快捷键修改

    eclipse 常用设置,常用快捷键,myeclipse和eclipse类似' 首先打开eclipse的首选项-->搜索 keys' 常用的一些快捷键: Ctrl+1 快速修复(最经典的快捷键, ...

  9. (转载)StringGrid常用属性和常用操作

    Delphi StringGrid常用属性和常用操作 StringGrid组件用于建立显示字符串的网格,与电子表格相似.它可使表格中的字符串和相关对象操作简单化.StringGrid组件提供了许多可控 ...

  10. (转载)Delphi StringGrid常用属性和常用操作

    Delphi StringGrid常用属性和常用操作 StringGrid组件用于建立显示字符串的网格,与电子表格相似.它可使表格中的字符串和相关对象操作简单化.StringGrid组件提供了许多可控 ...

随机推荐

  1. 单片机基础——使用GPIO扫描检测按键

    1. 准备工作 硬件准备 开发板首先需要准备一个小熊派IoT开发板,并通过USB线与电脑连接. 软件准备 需要安装好Keil - MDK及芯片对应的包,以便编译和下载生成的代码,可参考MDK安装教程 ...

  2. python 异步请求

    这是循环请求10次页面.总时间大概是10秒左右,如果是普通的循环请求10次页面而不添加异步的话,时间大概在30秒以上,当然这个数据可能有误,因为有网速的问题存在,但大体的效果应该是不变的. impor ...

  3. Vue2.0 【第一季】第6节 v-model指令

    目录 Vue2.0 [第一季] 第6节 v-model指令 第6节 v-model指令 一.一个最简单的双向数据绑定代码: 二.修饰符 三.文本区域加入数据绑定 四.多选按钮绑定一个值 五.多选绑定一 ...

  4. 《前端之路》- TypeScript(二) 函数篇

    目录 一.定义函数方法 二.定义函数传参 三.可选传参 四.默认传参 五.传递剩余参数 六.函数重载 七.箭头函数 八.总结 一.定义函数方法 在 es5 中定时函数的方法有 命名函数和函数表达式(匿 ...

  5. 从火箭发场景来学习Java多线程并发闭锁对象

    从火箭发场景来学习Java多线程并发闭锁对象 倒计时器场景 在我们开发过程中,有时候会使用到倒计时计数器.最简单的是:int size = 5; 执行后,size—这种方式来实现.但是在多线程并发的情 ...

  6. React利用Antd的Form组件实现表单功能(转载)

    一.构造组件 1.表单一定会包含表单域,表单域可以是输入控件,标准表单域,标签,下拉菜单,文本域等. 这里先引用了封装的表单域 <Form.Item /> 2.使用Form.create处 ...

  7. react 给选中的li添加样式(转载)

    路:使用事件委托,关键:获取到的index必须转为数字,因为它是字符串 handleClick = (e) => { const nodeName = e.target.nodeName.toU ...

  8. 关于IDEA的使用中,连接数据库console出现乱码的情况

    本人在连接数据库时也不算是出现乱码,因为乱码的解决方式百度都有,但是还是没有解决我当时遇到的问题, 首先排除navicat的问题,连接选择UTF-8的编码格式, 在Idea中使用debug调试,均可以 ...

  9. Linux 部署Tomcat图文注解 一学就会

    导读 安装tomcat前首先要安装对应的jdk并配置Java环境. 安装jdk,请参考:点我直达 安装Tomcat 下载Tomcat包 官网地址:点我直达 Tomcat与jdk兼容关系 注:Tomca ...

  10. 单片机的 HexToStr HexToBcd BcdToStr 几个转换函数

    今天写单片机一个程序 要检查一些数据,想发到串口调试的软件上在电脑上查看 有些转换函数 想网上找一个 看看都是很多的垃圾文章 很多的程序都不能用,那些发文章的人也不用心 所以我还是自己动手写一下吧 写 ...