常见的php设计模式
- 单例模式
- 工厂模式
- 注册器模式
- 适配器模式
- 策略模式
- 观察者模式
单例模式
- 减少多次实例化操作,单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
代码示例:
点击查看代码
<?php
namespace example;
/**
* Class Single
* @package example
* 简单单例模式
* 特点:三私一公
* 三私:私有的静态变量(存放实例)私有的构造方法(防止创建) 私有的克隆方法(防止克隆对象)
* 一公:公有的静态方法(对外界提供实例)
*/
class Database{
private $name;//声明一个私有的实例变量
private function __construct(){//声明私有构造方法为了防止外部代码使用new来创建对象。
}
private function __clone(){} //私有的克隆方法(防止克隆对象)
static public $instance;//声明一个静态变量(保存在类中唯一的一个实例)
static public function getinstance(){//声明一个getinstance()静态方法,用于检测是否有实例对象
if(!self::$instance) { //如果实例不存在则创建并存入静态变量
self::$instance = new self();
}
return self::$instance;
}
}
$class_db = Database::getinstance();
工厂模式
- 工厂模式是我们最常用的实例化对象模式,是用工厂方法代替new操作的一种模式。特点是减少耦合
代码示例:
点击查看代码
<?php
namespace example;
use example\Application;
//简单工厂模式
class Factory{
/**
* 如果某个类在很多的文件中都 new Student(),那么万一这个类的名字
* 发生变更或者参数发生变化,如果不使用工厂模式,就需要修改每一个PHP
* 代码,使用了工厂模式之后,只需要修改工厂类或者方法就可以了。
*/
public static function createStudentClass(){
// return new example\Databse();
$db = example/Database::getinstance();//调用上面的单例模式静态方法
example/Register::set('db1',$db); //将对象注册到全局的树上
return $db;
}
public static function getDatabase($id = 'proxy'){
if ($id == 'proxy')
{
if (!self::$proxy)
{
self::$proxy = new \example\Database\Proxy;
}
return self::$proxy;
}
$key = 'database_'.$id;
if ($id == 'slave')
{
$slaves = Application::getInstance()->config['database']['slave'];
$db_conf = $slaves[array_rand($slaves)];
}
else
{
$db_conf = Application::getInstance()->config['database'][$id];
}
$db = Register::get($key);
if (!$db) {
$db = new Database\MySQLi();
$db->connect($db_conf['host'], $db_conf['user'], $db_conf['password'], $db_conf['dbname']);
Register::set($key, $db);
}
return $db;
}
}
$db1 = Factory::createStudentClass();//创建一个类
$db1 = example/Register::get('db1');//调用创建的类
注册模式
- 注册模式,解决全局共享和交换对象。已经创建好的对象,挂在到某个全局可以使用的数组上,在需要使用的时候,直接从该数组上获取即可。将对象注册到全局的树上。任何地方直接去访问。
代码示例:
点击查看代码
<?php
namespace example;
/**
* Class Register
* @package example
* 注册模式
*/
class Register
{
protected static $objects;
//注册对象到全局的树上
/**
* @param $alias 类别名
* @param $object 对象
*/
static function set($alias, $object)
{
self::$objects[$alias] = $object;
}
//获取树上的对象
static function get($key)
{
if (!isset(self::$objects[$key]))
{
return false;
}
return self::$objects[$key];
}
//移除树上的对象
function _unset($alias)
{
unset(self::$objects[$alias]);
}
}
适配器模式
- 将各种截然不同的函数接口封装成统一的API。
代码示例:
点击查看代码
//定义一个接口类
<?php
namespace example\Database;
interface IDatabase
{
function connect($host, $user, $passwd, $dbname);//连接数据库
function query($sql);//执行sql
function close();//关闭连接
}
//mysql实现接口
<?php
namespace example\Database;
use example\Database\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 example\Database;
use example\Database\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 example\Database;
use example\Database\IDatabase;
class PDO implements IDatabase
{
/**
* @var \PDO
*/
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
namespace example\Database;
use example\Database\MySQL;
use example\Database\MySQLi;
use example\Database\PDO;
class index{
function index(){
$db = new MySQL();
$db1 = new MySQLi();
$db2 = new PDO();
$db->connect('127.0.0.1','root','123456',"test");
$db->query("show databases");
$db->close();
}
}
策略模式
- 策略模式是对象的行为模式,用意是对一组算法的封装。动态的选择需要的算法并使用。
代码示例:
点击查看代码
//定义一个商城首页类
<?php
namespace example;
class page{
/**
* @var \example\userStrategy
*/
protected $strategy;
function index(){
// if (isset($_GET['man'])){
// echo "AD:";
// echo "ASUS笔记本电脑";
// echo "category:";
// echo "电子产品";
// }else{
// echo "Ad:";
// echo "2021新款女装";
// echo "category:";
// echo "女装";
// }
echo "Ad:";
$this->strategy->showAd();
echo "category:";
$this->strategy->showCategory();
}
function setStrategy(\example\userStrategy $strategy){
$this->strategy = $strategy;
}
}
if ($_GET['man']){
$strategy = new \example\ManUser();
}else{
$strategy = new \example\WomenUser();
}
$page = new page();
$page->setStrategy($strategy);
$page->index();
$user = new User(1);
$user_info = $user->data;//获取用户信息
//修改用户信息
$user->username = "张三";
$user->tel = "18310311114";
//定义一个策略接口类
<?php
namespace example;
interface userStrategy
{
function showAd();
function showCategory();
}
//针对女性用户实现策略接口
<?php
namespace example;
use example\userStrategy;
class WomenUser implements userStrategy
{
function showAd()
{
echo "2021新款女装";
}
function showCategory()
{
echo "女装";
}
}
//针对男性用户实现策略接口
<?php
namespace example;
use example\userStrategy;
class ManUser implements userStrategy
{
function showAd()
{
echo "ASUS笔记本电脑";
}
function showCategory()
{
echo "电子产品";
}
}
观察者模式
- 当一个对象状态发生变化时,依赖它的对象全部会收到通知,并自动更新。观察者模式实现了低耦合,非侵入式的通知与更新机制。
代码示例:
点击查看代码
//定义一个更新操作的接口类
<?php
namespace example;
interface Observer
{
function update($event_info = null);
}
//定义一个观察者模式抽象类
<?php
namespace example;
/**
* Class EventGenerator
* @package example
* 观察者模式
*/
abstract class EventGenerator { //声明一个抽象类
private $observers = array();
/**
* @param Observer $observer
* 添加观察者
*/
function addObserver(Observer $observer)
{
$this->observers[] = $observer;
}
/**
* 通知观察者更新
*/
function notify()
{
foreach($this->observers as $observer)
{
$observer->update();
}
}
}
//观察者模式实现
<?php
namespace example;
/**
* Class Event
* @package example
* 观察者模式 :当一个对象状态发生改变后依赖他的对象全部会收到通知并自动更新
* 特点:实现了低耦合,非侵入式的通知与更新机制
*/
class Event extends \example\EventGenerator {
function trigger(){
echo "event";//事件发生
echo "逻辑1\n";
echo "逻辑2\n";
echo "逻辑3\n";
echo "逻辑4\n";
$this->notify();
}
}
class Observer1 implements \example\Observer{
function update($event_info = null)
{
echo "逻辑1\n";
}
}
class Observer2 implements \example\Observer{
function update($event_info = null)
{
echo "逻辑2\n";
}
}
//增加观察者
$event = new Event();
$event->addObserver(new Observer1());
$event->addObserver(new Observer2());
其他
- 装饰器模式:动态的给一个类添加功能
- 数据对象映射模式:数据对象映射模式是将对象和数据库存储映射起来,对一个对象的操作会映射为对数据库的操作。
- 依赖注入模式:依赖注入(Dependency Injection)是控制反转(Inversion of Control)的一种实现方式。
控制反转是当调用者需要被调用者协助时,在传统的程序设计过程中,通常由调用者的实例,但在这里,创建被调用者的工作不再由调用者来完成,而是将被调用者的创建移到调用者的外部,从而反转被调用者的创建,消除了调用者对被调用者的控制,因此称为控制反转。
面向对象编程的基本原则
- 单一职责:一个类,只需要做好一件事。
- 开放封闭:一个类,应该是可扩展的,而不可修改的。
- 依赖倒置:一个类,不应该强依赖另一个类,每个类对于另外一个类都是可以替换的。
- 配置化 :应该尽可能的使用配置,而不是硬编码。
- 面向接口编程:只需要关注接口,不需要关心实现。