PHP 常见设计模式及示例

这篇具有很好参考价值的文章主要介绍了PHP 常见设计模式及示例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

PHP 常见设计模式及示例,PHP,php,设计模式,android

1.单例模式

单例模式顾名思义,就是只有一个实例。作为对象的创建模式, 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

单例模式的要点有三个:

  • 一是某个类只能有一个实例;
  • 二是它必须自行创建这个实例;
  • 三是它必须自行向整个系统提供这个实例。

为什么要使用PHP单例模式

  1. php的应用主要在于数据库应用, 一个应用中会存在大量的数据库操作, 在使用面向对象的方式开发时, 如果使用单例模式, 则可以避免大量的new 操作消耗的资源,还可以减少数据库连接这样就不容易出现 too many connections情况。
  2. 如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看zend Framework的FrontController部分。
  3. 在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。

例子:

控制层使用
...

use app\index\model\Users as UsersModel;

...

/**
* 添加一条数据
*/
public function add(){
    $u_id = intval(input('id'));
    $u_name = input('name');
    $u_age = 18;
    $u_sex = 0;
    $insertOne = UsersModel::insertOne($u_id,$u_name,$u_age,$u_sex);
    if($insertOne){
        $this->success("插入".$u_name."成功");
    }
    else{
        $this->error("插入".$u_name."失败");
    }
}

model层
<?php
namespace app\index\model;

use think\Model;
use think\Db;
/**
 * 使用静态方法 static 而不是 public 在controller里面不用new 直接用 会方便很多
 */
class Users extends Model
{
    private static $instance;
    protected $defaultField = 'danli';
    private function __clone(){} //禁止被克隆
    /**
    * 单例
    */
    public static function getInstance()
    {
        if(!(self::$instance instanceof self)){
            self::$instance = new static();
        }
        return self::$instance;
    }
    /**
    * 添加一条数据
    */
    public static function insertOne($uid,$uname,$uage,$usex)
    {
          $inserttheone = self::getInstance()->execute("insert into users(u_id,u_name,u_age,u_sex) value(".$uid.",'".$uname."',".$uage.",".$usex.")");
          if($inserttheone)
          {
          	return true;
          }
          else{
          	return false;
          }
    }
  /**
  * 删除一条数据
  */
  public static function deleteOne($uid){
    $delone = self::getInstance()->execute("delete from users where u_id = ".$uid."");
    if($delone){
    	return true;
    }else{
   	 	return false;
    }
  }
  /**
  *  修改一条数据
  */
  public static function updateOne($uid,$age){
    $updateone = self::getInstance()->execute("update users set u_age = ".$age." where u_uid = ".$uid."");
    if($updateone){
    	return true;
    }else{
    	return false;
    }
  }
  /**
  * 查询
  */
  public static function query($defaultField,$uid){
  	if($defaultField == '' || empty($defaultField) || is_null($defaultField)){
  		$defaultField = '*';
  	}
    if($uid == '' || empty($uid) || is_null($uid)){
      $uid = '';
    }else{
      $uid = "where u_id = $uid";
    }
    return self::getInstance()->query("select $defaultField from users $uid");

  }
  /**
  * 批量修改
  */
  public static function batchUpdate($arr)
  {
    foreach ($arr as $key => $value) {
      $updatearr = self::getInstance()->execute("update users set u_name = '".$value['u_name']."',u_age = ".$value['u_age'].",u_sex = ".$value['u_sex']." where u_uid = ".$uid."");
      if($updatearr){
           return true;
      }else{
         return false;
      }
      }
    }
  }

/**
* 设计模式之单例模式
* $_instance必须声明为静态的私有变量
* 构造函数必须声明为私有,防止外部程序new类从而失去单例模式的意义
* getInstance()方法必须设置为公有的,必须调用此方法以返回实例的一个引用
* ::操作符只能访问静态变量和静态函数
* new对象都会消耗内存
* 使用场景:最常用的地方是数据库连接。
* 使用单例模式生成一个对象后,该对象可以被其它众多对象所使用。
*/
class man
{
//保存例实例在此属性中
private static $_instance;

//构造函数声明为private,防止直接创建对象
private function __construct()
{
echo '我被实例化了!';
}

//单例方法
public static function get_instance()
{
  var_dump(isset(self::$_instance));

  if(!isset(self::$_instance))
  {
  self::$_instance=new self();
  }
  return self::$_instance;
}

//阻止用户复制对象实例
private function __clone()
{
	trigger_error('Clone is not allow' ,E_USER_ERROR);
}

function test()
{
	echo("test");
}
}

// 这个写法会出错,因为构造方法被声明为private
//$test = new man;

// 下面将得到Example类的单例对象
$test = man::get_instance();
$test = man::get_instance();
$test->test();

// 复制对象将导致一个E_USER_ERROR.
//$test_clone = clone $test;

2.简单工厂模式


①抽象基类:类中定义抽象一些方法,用以在子类中实现
②继承自抽象基类的子类:实现基类中的抽象方法
③工厂类:用以实例化所有相对应的子类

/**
*
* 定义个抽象的类,让子类去继承实现它
*
*/
abstract class Operation{
//抽象方法不能包含函数体
abstract public function getValue($num1,$num2);//强烈要求子类必须实现该功能函数
}

/**
* 加法类
*/
class OperationAdd extends Operation {
  public function getValue($num1,$num2){
  return $num1+$num2;
  }
}
/**
* 减法类
*/
class OperationSub extends Operation {
  public function getValue($num1,$num2){
  return $num1-$num2;
  }
}
/**
* 乘法类
*/
class OperationMul extends Operation {
  public function getValue($num1,$num2){
  return $num1*$num2;
  }
}
/**
* 除法类
*/
class OperationDiv extends Operation {
  public function getValue($num1,$num2){
    try {
      if ($num2==0){
      	throw new Exception("除数不能为0");
      }else {
      	return $num1/$num2;
      }
    }catch (Exception $e){
    	echo "错误信息:".$e->getMessage();
    }
  }
}

通过采用面向对象的继承特性,我们可以很容易就能对原有程序进行扩展,比如:‘乘方’,‘开方’,‘对数’,‘三角函数’,‘统计’等,以还可以避免加载没有必要的代码。

如果我们现在需要增加一个求余的类,会非常的简单

我们只需要另外写一个类(该类继承虚拟基类),在类中完成相应的功能(比如:求乘方的运算),而且大大的降低了耦合度,方便日后的维护及扩展

/**
* 求余类(remainder)
*
*/
class OperationRem extends Operation {
  public function getValue($num1,$num2){
  return $num1%$num12;
  }
}

现在还有一个问题未解决,就是如何让程序根据用户输入的操作符实例化相应的对象呢?
解决办法:使用一个单独的类来实现实例化的过程,这个类就是工厂

/**
* 工程类,主要用来创建对象
* 功能:根据输入的运算符号,工厂就能实例化出合适的对象
*
*/
class Factory{
  public static function createObj($operate){
    switch ($operate){
      case '+':
        return new OperationAdd();
        break;
      case '-':
        return new OperationSub();
        break;
      case '*':
        return new OperationSub();
        break;
      case '/':
        return new OperationDiv();
        break;
      }
    }
  }
$test=Factory::createObj('/');
$result=$test->getValue(23,0);
echo $result;

其他关于关于此模式的笔记:

工厂模式:

以交通工具为例子:要求请既可以定制交通工具,又可以定制交通工具生产的过程

1 > 定制交通工具

  • 1.定义一个接口,里面包含交工工具的方法(启动 运行 停止)
  • 2.让飞机,汽车等类去实现他们

2 > 定制工厂(通上类似)

  • 1.定义一个接口,里面包含交工工具的制造方法(启动 运行 停止)
  • 2.分别写制造飞机,汽车的工厂类去继承实现这个接口

demo

简单工厂模式

介绍:
简单工厂模式又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类

简单工厂模式最大的优点在于实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责,但是其最大的缺点在于工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,而且产品较多时,工厂方法代码将会非常复杂。

<?php
//简单工厂模式
class Cat{
  function __construct(){
      echo "I am Cat class <br>";
	}
}
class Dog{
	function __construct(){
      echo "I am Dog class <br>";
  }
}
class Factory{
  public static function CreateAnimal($name){
    if ($name == 'cat') {
    	return new Cat();
    } elseif ($name == 'dog') {
    	return new Dog();
    }
  }
}

$cat = Factory::CreateAnimal('cat');
$dog = Factory::CreateAnimal('dog');
工厂方法模式

工厂方法模式是简单工厂模式的进一步抽象和推广。

由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。

在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。

这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。

<?php
interface Animal{
  public function run();
  public function say();
}

class Cat implements Animal{
    public function run(){
        echo "I ran slowly <br>";
    }
    public function say(){
      echo "I am Cat class <br>";
    }
}

class Dog implements Animal{
    public function run(){
      echo "I'm running fast <br>";
    }
    public function say(){
      echo "I am Dog class <br>";
    }
}
  
abstract class Factory{
  	abstract static function createAnimal();
}
  
class CatFactory extends Factory{
  	public static function createAnimal(){
    	return new Cat();
    }
}
  
class DogFactory extends Factory{
    public static function createAnimal(){
    	return new Dog();
    }
}

$cat = CatFactory::createAnimal();
$cat->say();
$cat->run();

$dog = DogFactory::createAnimal();
$dog->say();
$dog->run();
抽象工厂模式

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。

此模式是对工厂方法模式的进一步扩展。在工厂方法模式中,一个具体的工厂负责生产一类具体的产品,即一对一的关系,但是,如果需要一个具体的工厂生产多种产品对象,那么就需要用到抽象工厂模式了。

<?php

interface TV{
  public function open();
  public function use();
}

class HaierTv implements TV{
  public function open()
  {
      echo "Open Haier TV <br>";
  }

  public function use(){
    echo "I'm watching TV <br>";
  }
}

interface PC{
  public function work();
  public function play();
}

class LenovoPc implements PC
{
  public function work()
  {
  	echo "I'm working on a Lenovo computer <br>";
  }
  public function play()
  {
  	echo "Lenovo computers can be used to play games <br>";
  }
}

abstract class Factory{
  abstract public static function createPc();
  abstract public static function createTv();
}

class ProductFactory extends Factory
{
    public static function createTV(){
    	return new HaierTv();
    }
    public static function createPc(){
      return new LenovoPc();
    }
}

$newTv = ProductFactory::createTV();
$newTv->open();
$newTv->use();

$newPc = ProductFactory::createPc();
$newPc->work();
$newPc->play();

3.观察者模式

观察者模式属于行为模式,是定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。它完美的将观察者对象和被观察者对象分离。可以在独立的对象(主体)中维护一个对主体感兴的依赖项(观察器)列表。 让所有观察器各自实现公共的 Observer接口,以取消主体和依赖性对象之间的直接依赖关系。(反正我看不明白)

用到了 spl (standard php library)

class MyObserver1 implements SplObserver {
  public function update(SplSubject $subject) {
      echo __CLASS__ . ' - ' . $subject->getName();
    }
}

class MyObserver2 implements SplObserver {
  public function update(SplSubject $subject) {
  	echo __CLASS__ . ' - ' . $subject->getName();
  }
}

class MySubject implements SplSubject {
  private $_observers;
  private $_name;

  public function __construct($name) {
    $this->_observers = new SplObjectStorage();
    $this->_name = $name;
  }

  public function attach(SplObserver $observer) {
  	$this->_observers->attach($observer);
  }

  public function detach(SplObserver $observer) {
  	$this->_observers->detach($observer);
  }

  public function notify() {
    foreach ($this->_observers as $observer) {
    	$observer->update($this);
    }
  }

  public function getName() {
    return $this->_name;
    }
  }

  $observer1 = new MyObserver1();
  $observer2 = new MyObserver2();

  $subject = new MySubject("test");

  $subject->attach($observer1);
  $subject->attach($observer2);

  $subject->notify();

参考原文:http://www.php.net/manual/zh/class.splsubject.php

4.策略模式

在此模式中,算法是从复杂类提取的,因而可以方便地替换。例如,如果要更改搜索引擎中排列页的方法,则策略模式是一个不错的选择。思考一下搜索引擎的几个部分 —— 一部分遍历页面,一部分对每页排列,另一部分基于排列的结果排序。在复杂的示例中,这些部分都在同一个类中。通过使用策略模式,您可将排列部分放入另一个类中,以便更改页排列的方式,而不影响搜索引擎的其余代码。

作为一个较简单的示例,下面 显示了一个用户列表类,它提供了一个根据一组即插即用的策略查找一组用户的方法

策略模式,生活中的实例:

例如下班回家,我可以有几个策略考虑:我可以骑单车,乘坐公交车,乘地铁等策略

还比如网站开发个人中心页面,不同的用户类型显示个人主页不一样,这个可以使用策略模式,即针对不同的用户使用不同的策略。

//定义接口
interface IStrategy {
	function filter($record);
}

//实现接口方式1
class FindAfterStrategy implements IStrategy {
  private $_name;
  public function __construct($name) {
  $this->_name = $name;
}
public function filter($record) {
	return strcmp ( $this->_name, $record ) <= 0;
}
}

//实现接口方式1
class RandomStrategy implements IStrategy {
  public function filter($record) {
  	return rand ( 0, 1 ) >= 0.5;
  }
}

//主类
class UserList {
private $_list = array ();
public function __construct($names) {
  if ($names != null) {
    foreach ( $names as $name ) {
   		 $this->_list [] = $name;
  	}
  }
}

public function add($name) {
	$this->_list [] = $name;
}

public function find($filter) {
$recs = array ();
foreach ( $this->_list as $user ) {
    if ($filter->filter ( $user ))
    	$recs [] = $user;
    }
   		 return $recs;
    }
}

$ul = new UserList ( 
	array (
    "Andy",
    "Jack",
    "Lori",
    "Megan"
	) 
	);
$f1 = $ul->find ( new FindAfterStrategy ( "J" ) );
print_r ( $f1 );

$f2 = $ul->find ( new RandomStrategy () );

print_r ($f2);

策略模式非常适合复杂数据管理系统或数据处理系统,二者在数据筛选、搜索或处理的方式方面需要较高的灵活性

其他demo

//抽象策略类
abstract class BaseUserStratege{
	abstract public function center();//个人中心
}
//具体策略普通用户策略
class CommonUserStratege extends BaseUserStratege{
  public function center()
  {
  echo 'common user center';
  }
}
//具体策略VIP用户策略
class VipUserStratege extends BaseUserStratege{
  public function center()
  {
  	echo 'vip user center';
  }
}
//环境角色,对抽象策略类的引用
class UserStrategeContext{
  private $baseUserStratege = null;
  public function __construct($baseUserStratege){
  	$this->baseUser = $baseUser;
  }
  public function center(){
  	return $this->baseUserStratege->center();
	}
}

//根据不同用户类型创建不同的具体决策类,比如vip用户,就创建VipUser策略
$user = new VipUserStratege();
$userStrategeContext = new UserStrategeContext($user);
$userStrategeContext->center();

注册模式

注册模式,解决全局共享和交换对象。

已经创建好的对象,挂在到某个全局对象树(可以是数组),在需要使用的时候,直接从该对象树上获取即可。

class Register{
  protected static $objects;//注意是static变量
  //将对象注册到全局的树上
  public function set($alias,$object){
  	self::$objects[$alias] = $object;
  }
  //获取某个注册到树上的对象
  public function get($alias){
  	return self::$objects[$alias];
  }
  //移除某个注册到树上的对象。
  public function delete($alias){
    unset(self::$objects[$alias]);
  }
}

适配器模式

将各种截然不同的函数接口封装成统一的API

PHP中的数据库操作有MySQL,MySQLi,PDO三种,可以用适配器模式统一成一致,使不同的数据库操作,统一成一样的API。文章来源地址https://www.toymoban.com/news/detail-822983.html

## 接口 IDatabase

<?php
interface IDatabase
{
    function connect($host, $user, $passwd, $dbname);
    function query($sql);
    function close();
}

## MySQL

<?php
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

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);
  }
}

到了这里,关于PHP 常见设计模式及示例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • javascript设计模式-应用示例

    有些时候为了适应没的场景,有些代码没必要每次调用时都进行一次环境判断,所以可以memoizing技术动态改写运行中代码的实现。 发起多个请求,程序会自动缓存,并通过setTimeOut重复调用。 这个例子充分应用了通道方法,利用此模式应该可以做到AOP的功能。

    2024年01月23日
    浏览(43)
  • 设计模式-外观模式在Java中的使用示例

    外观模式是一种使用频率非常高的结构型设计模式,它通过引入一个外观角色来简化客户端与子系统 之间的交互,为复杂的子系统调用提供一个统一的入口,降低子系统与客户端的耦合度,且客户端调用非常方便。 示例 自己泡茶和去茶馆喝茶的区别,如果是自己泡茶需要自

    2024年02月17日
    浏览(47)
  • 设计模式-建造者模式在Java中使用示例

    复杂对象的组装与创建 没有人买车会只买一个轮胎或者方向盘,大家买的都是一辆包含轮胎、方向盘和发动机等多个部件的完整汽车。 如何将这些部件组装成一辆完整的汽车并返回给用户,这是建造者模式需要解决的问题。 建造者模式又称为生成器模式,它是一种较为复杂

    2024年02月16日
    浏览(49)
  • JAVA 23种设计模式示例

    目录 一.单例模式 二.工厂方法模式 三.抽象工厂模式 四.建造者模式 五.原型模式 六.享元模式 七.门面模式 八.适配器模式 九.装饰者模式 十.策略模式 十一.模板方法模式 十二.观察者模式 十三.责任链模式 十四.代理模式 十五.桥接模式 十六.组合模式 十七.命令模式 十八.状态

    2024年02月13日
    浏览(40)
  • 【C++设计模式之原型模式:创建型】分析及示例

    简介 原型模式(Prototype Pattern)是一种创建型设计模式,它允许通过复制已有对象来生成新的对象,而无需再次使用构造函数。 描述 原型模式通过复制现有对象来创建新的对象,而无需显式地调用构造函数或暴露对象的创建细节。它使用原型接口来声明克隆方法,所有实现

    2024年02月07日
    浏览(39)
  • 【设计模式】builder 创建者设计模式详解(包含电商应用场景及代码示例)

    在常见的设计模式中,“Builder” 通常是指一种设计模式,而不是具体的类或方法。Builder 模式是一种创建型设计模式,其目的是通过提供一个独立的构建器类来构建一个复杂对象。 建造者模式 (Builder Pattern) 是一种创建型设计模式,它的主要目标是为了将一个复杂对象的构

    2024年01月21日
    浏览(49)
  • 【C++设计模式之装饰模式:结构型】分析及示例

    装饰模式(Decorator Pattern)是一种结构型设计模式,它允许在运行时动态地给一个对象添加额外的行为。 描述 装饰模式通过创建一个包装器(Wrapper)来包裹原始对象,并在原始对象的行为前后添加额外的功能。通过这种方式,可以实现在不改变原始对象结构的情况下,动态

    2024年02月07日
    浏览(38)
  • 【设计模式】工厂方法模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    【设计模式】工厂方法模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )_工厂方法模式的优缺点_韩曙亮的博客-CSDN博客

    2024年02月16日
    浏览(42)
  • Java设计模式:简介与常见模式

    Java中常见的设计模式有很多,以下是其中一些常见的设计模式及其作用、优势和适用场景: 作用:确保一个类只有一个实例,并提供全局访问点。 优势:节约系统资源,避免多个实例造成的冲突。 适用场景:需要限制类的实例化次数,例如线程池、数据库连接池。 作用:

    2024年02月09日
    浏览(59)
  • 设计模式-职责链模式在Java中使用示例-采购审批系统

    采购审批是分级进行的,即根据采购金额的不同由不同层次的主管人员来审批,主任可以审批5万元以下(不包括5万元) 的采购单,副董事长可以审批5万元至10万元(不包括10万元)的采购单,董事长可以审批10万元至50万元(不包括50万元) 的采购单,50万元及以上的采购单

    2024年02月16日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包