PHP设计模式

2019-05-17 11:52:00
linefo
原创
397


设计模式应该是通用各种语言的,但考虑到不同语言的特性,实现上还是有所区别。

这里以PHP为语言。


1、依赖注入(DI)/控制反转(IoC)


这里转自:https://segmentfault.com/a/1190000007209266?utm_source=tag-newest


依赖注入和控制反转描述是同一种东西,仅是从不同角度而言。

从字面上难以理解。

做一个大概的描述,看不懂正常,我也看不懂:

这种设计模式用来减少程序间的耦合,最重要的一点好处就是有效的分离了对象和它所需要的外部资源,使得它们松散耦合,有利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。依赖注入是从应用程序的角度在描述,可以把依赖注入,即:应用程序依赖容器创建并注入它所需要的外部资源;而控制反转是从容器的角度在描述,即:容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源。


【问答】


  1. 整个过程中参与者都有谁?

    一般有三方参与者,一个是某个对象;一个是IoC/DI的容器;另一个是某个对象的外部资源。
    某个对象指的就是任意的、普通的PHP对象; 
    IoC/DI的容器简单点说就是指用来实现IoC/DI功能的一个框架程序;
    对象的外部资源指的就是对象需要的,但是是从对象外部获取的,都统称资源,比如:对象需要的其它对象、或者是对象需要的文件资源等等。
  2. 谁依赖于谁:

    当然是某个对象依赖于IoC/DI的容器
  3. 为什么需要依赖:

    对象需要IoC/DI的容器来提供对象需要的外部资源
  4. 谁注入于谁:

    是IoC/DI的容器 注入 某个对象
  5. 到底注入什么:

    就是注入某个对象所需要的外部资源
  6. 谁控制谁:

    当然是IoC/DI的容器来控制对象了
  7. 控制什么:

    主要是控制对象实例的创建
  8. 为何叫反转:

    反转是相对于正向而言的,那么什么算是正向的呢?
    考虑一下常规情况下的应用程序,如果要在A里面使用C,你会怎么做呢?当然是直接去创建C的对象,也就是说,是在A类中主动去获取所需要的外部资源C($c = new C();),这种情况被称为正向的。那么什么是反向呢?就是A类不再主动去获取C,而是被动等待,等待IoC/DI的容器获取一个C的实例,然后反向的注入到A类中。
    


用图例来说明一下,先看没有IoC/DI的时候,常规的A类使用C类的示意图,如下图所示:


代码示意:

<?php
/**
 * 没有IoC/DI的时候,常规的A类使用C类的示例
 */

/**
 * Class c
 */
class c
{
    public function say()
    {
        echo 'hello';
    }
}

/**
 * Class a
 */
class a
{
    private $c;
    public function __construct()
    {
        $this->c = new C(); // 实例化创建C类
    }

    public function sayC()
    {
        echo $this->c->say(); // 调用C类中的方法
    }
}

$a = new a();
$a->sayC();


当有了IoC/DI的容器后,A类不再主动去创建C了,如下图所示:


而是被动等待,等待IoC/DI的容器获取一个C的实例,然后反向的注入到A类中,如下图所示:


代码示意:


<?php
/**
 * 当有了IoC/DI的容器后,a类依赖c实例注入的示例
 */

/**
 * Class c
 */
class c
{
    public function say()
    {
        echo 'hello';
    }
}

/**
 * Class a
 */
class a
{
    private $c;
    public function setC(C $c)
    {
        $this->c = $c; // 实例化创建C类
    }

    public function sayC()
    {
        echo $this->c->say(); // 调用C类中的方法
    }
}

$c = new C();
$a = new a();
$a->setC($c);
$a->sayC();


9. 什么是正转?正转就是按照普通的我们再类中直接创建对象实例,如 $c = new C();


【总结】

其实IoC/DI对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC/DI容器来创建并注入它所需要的资源了。


2、门面模式/外观模式(Facade)


这个要从业务逻辑上来讲。

本质上来说,是为零散的、较基本的功能/子系统,提供一个对外接口,该接口包含一系列功能/子系统,最后接口能完成一整个功能。


一个简单的示例:


<?php
	// 食材类
	Class Foods{
		// 得到青瓜
		public function cucumber(){
			return '青瓜';
		}
		// 得到鸡蛋
		public function egg(){
			return '鸡蛋';
		}
	}
	
	// 操作类
	Class Operate{
		// 炒菜
		public function decoction(array $foods){
			return '炒了'.implode($foods, '和');
		}
	}
	
	// 菜肴类:一个典型的Facede
	Class Dishes{
		// 菜色1:炒青瓜
		public function dish1(){
			$Foods = new Foods();
			$Operate = new Operate();
			 // 拿到青瓜
			$foods1 = $Foods->cucumber();
			echo $Operate->decoction([$foods1]);
		}
		// 菜色2:炒青瓜和鸡蛋
		public function dish2(){
			$Foods = new Foods();
			$Operate = new Operate();
			 // 拿到青瓜和鸡蛋
			$foods1 = $Foods->cucumber();
			$foods2 = $Foods->egg();
			echo $Operate->decoction([$foods1, $foods2]);
		}
	}
	
	$Dishes = new Dishes();
	// 菜色1:炒青瓜
	$Dishes->dish1();
	
	// 仅分隔
	echo '<br />';
	
	// 菜色2:炒青瓜和鸡蛋
	$Dishes->dish2();



最基本的概念就是这样了。其实就是当拥有较为零散的功能以后,把认为可以整合的、经常被使用到的功能合起来做成一个接口。

文章分类
联系我们
联系人: Mr.Chen
QQ: 185391277