设计模式的一些小整理

💻设计模式

设计模式概述

	设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。
	模式的经典定义:每个模式都描述了一个在我们的环境中不断出现的问题,然后描述了该问题的解决方案的核心,通过这种方式,我们可以无数次地重用那些已有的解决方案,无需再重复相同的工作。即模式是在特定环境中解决问题的一种方案 
	现在有两派,有的人建议使用设计模式,有的人不建议使用设计模式!

解决代码的耦合度
耦合度越低越好
高内聚低耦合(对内要高内聚,对外要低耦合)
设计模式不分语言。php是世界上最优美的语言

1 单例模式

这个类只能创建一个对象

php的应用主要在于数据库的应用,一个应用会出现大量的数据库操作,使用单例模式,可以避免大量的操作消耗的资源

步骤:

  1. 构造函数需要标记为private

  2. 保存类实例的静态成员变量

  3. 获取实例的公共的静态方法

    class Dog
    {
    //设置一个静态的成员属性来保存单例对象
    static private $instance;
    //将构造函数私有化
    private function getInstance()
    {
    if(self::$instance){
    self::$instances = new self();
    }
    return self::$instance;
    }

    }
    //调用的时候就调用这个函数
    $dog1 = Dog::getInstance();
    $dog2 = Dog::getInstance();
    if ($dog1 === $dog2) {
    echo '这是同一条狗
    ';
    } else {
    echo '这不是同一条狗
    ';
    }

2 简单工厂、标准工厂

	接口中定义一些方法
	实现接口的类实现这些方法
	工厂类:用以实例化对象
	优点:为系统结构提供了灵活的动态扩展机制。方便维护
	步骤
		1、根据类调用一个静态方法,传递一个你想要创造什么样对象的额参数
			就可以获得这个类
		2、有一个接口
		3、各个类型实现这些接口

/***************简单工厂模式***********************/
		interface Skill
		{
			function family();
			function buy();
		}

		class Human implements Skill
		{
			function family()
			{
				echo '人族在辛辛苦苦的伐木累<br />';
			}
			function buy()
			{
				echo '人族买了一个国王祭坛<br />';
			}
		}
		class JingLing implements Skill
		{
			function family()
			{
				echo '精灵族在绕树转圈,吸取大树的日月精华<br />';
			}
			function buy()
			{
				echo '精灵族买了一个战争古树<br />';
			}
		}

		class Animal implements Skill
		{
			function family()
			{
				echo '兽族在卯足了劲与树对干<br />';
			}
			function buy()
			{
				echo '兽族买了一个灵族祭坛<br />';
			}
		}
		class NoDie implements Skill
		{
			function family()
			{
				echo '不死族在大口大口的吃树<br />';
			}
			function buy()
			{
				echo '不死族买了一个墓地<br />';
			}
		}
		#根据你给的类型switch出你要new的对象
		class Factory
		{
			static function makeHero($type)
			{
				switch ($type) {
					case 'humans':
						return new human();
						break;
					case 'jingling':
						return new JingLing();
						break;
					case 'animal':
						return new Animal();
						break;
					case 'nodie':
						return new NoDie();
						break;
				}

			}
		}
		#调用的时候是调用工厂里面的静态函数 
		$human = Factory::makeHero('animal');
		echo $human->family();

3 工厂模式

工厂方法模式核心是工厂类不再负责所有对象的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,它仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节

	1:首先给工厂一个接口标准	
	2:然后各种类型去继承这些接口
	3:然后又一个工厂接口,静态的方法
	4:各个工厂自己去实现自己的接口来创造手机
	5:最终想要什么类型的,就用该类型自己的工厂去调用静态函数去实现

interface Tell
{
	function call();
  	function recieve();
}
class xiaoMi implements Tell
{
  function call()
   {
     echo '我在用小米手机打电话'.'<br/>';
   }
  function recieve()
  {
    echo '我在用小米手机接电话'.'<br/>';
  }
}
class meiZu implements Tell
{
  function call()
   {
     echo '我在用meiZu手机打电话'.'<br/>';
   }
  function recieve()
  {
    echo '我在用meiZu手机接电话'.'<br/>';
  }
}
/***********************************************/
interface Factory
{
  static function makePhone();
}
class xiaomiFactory implements Factory
{
	function makePhone()
      {
        return new xiaoMi();
      }
}
class meizuFactory implements Factory
{
	function makePhone()
      {
        return new meiZu();
      }
}
/******************************************/
$phone = meizuFactory::makePhone();
echo $phone->recieve();

4 观察者模式

涉及到两个类:

		@-@一个是被观察者
			1、添加观察者
			2、删除观察者
			3、发送通知
		@-@一个是观察者
			1、做出反应即可
在php中:用户注册(收到邮件,收到短信,或者收到其他信息)
	它是一种事件系统,意味着这一模式允许某个类观察另一个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作;
	观察者模式提供了避免组件之间紧密耦合的另一种方法。

官方接口

			SplSubject
				attach  添加观察者
				detach  删除观察者
				notify  通知
			SplOberser
				update  做出响应

/**************被观察者*****************************/
class SuperBoy
	{
		#我可以有自己的观察者,放在数组里
		public $observers = [];
		#添加观察者的时候会传进来一个人是对象,然后把这个人放在数组里
		function addObserver($observer)
		{
			$this->observers[] = $observer;
		}
		#删除观察者的时候也是找到传入的这个人的键删掉
		function deleteObserver($observer)
		{
			$key = array_search($observer,$this->observers);
			unset($this->observers[$key]);
		}
		// 有通知观察者的做法,也就是让观察者做出反应
		function notice()
		{
			foreach ($this->observers as $observer) 
			{
				// 让这些对象分别去调用做出反应的方法
				foreach ($this->observers as $observer) {
					$observer->findYou();
				}
			}
		}
		function kf()
		{
			$this->notice();
		}

	}
	// 观察者只需要做出反应即可
	class Girl
	{
		function findYou()
		{
			echo '老娘就知道你在外面不老实,我哪里不如她<br />';
		}
	}
/************************************************/
	$hututu = new Girl();
	$huchunchun = new Girl();
	$lihui = new Girl();

	$obj = new SuperBoy();

	$obj->addObserver($hututu);
	$obj->addObserver($huchunchun);
	$obj->addObserver($lihui);
	$obj->kf();

5 适配器模式

生活中就有很多适配器 电源适配器 就是里面的变压器 220v

	可将一个类的接口转换成客户希望的另外一个接口,使得原本不兼容的接口能够一起工作。通俗的理解就是将不同接口适配成统一的接口
	1:当一个类实现外面的接口的时候,会通过传递一个对象,调用这个对象的方法
	2:在接口函数里面调用对象的方法

interface SuperMan
{
  function cook();
  function writePhp();
}
class Mans
{
    function cook()
    {
        echo __CLASS__ . '<br/>';
        echo "我会做宫保鸡丁";
    }
}
/***************这里是核心******************/
class CodeMonkey implements SuperMan
	{
		public $Man;
		function __construct($Man)
		{
			$this->Man = $Man;
		}
		function cook ()
		{
			$this->Man->cook();
		}
		function writePhp()
		{
			echo '我不仅会写php代码,我还会java、oc、c++、c#、c、go、js<br />';
		}
	}

	$xiaohuihui = new Mans();
	$xiang = new CodeMonkey($xiaohuihui);
	$xiang->cook();
	$xiang->writePhp();

6 策略模式

	(1)多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。
	(2)需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。
	(3)对客户隐藏具体策略(算法)的实现细节,彼此完全独立。
	(4)客户端必须知道所有的策略类,并自行决定使用哪一个策略类,策略模式只适用于客户端知道所有的算法或行为的情况。
	(5)策略模式造成很多的策略类,每个具体策略类都会产生一个新类。
	优点:
		1、策略模式提供了管理相关的算法族的办法
		2、算法封闭在独立的Strategy类中使得你可以独立于其Context改变它
		3、使用策略模式可以避免使用多重条件转移语句

7 门面模式

	优点
		1、它对客户屏蔽了子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便
		2、实现了子系统与客户之间的松耦合关系
		3、如果应用需要,它并不限制它们使用子系统类。因此可以在系统易用性与能用性之间加以选择
	适用场景
		1、为一些复杂的子系统提供一组接口
		2、提高子系统的独立性
		3、在层次化结构中,可以使用门面模式定义系统的每一层的接口

interface JiPai
{
  function want();
  function cook();
}
class XXJipai
{
    function naoyou()
    {
        echo '脑油味鸡排<br />';
    }
    function biti()
    {
        echo '鼻涕味鸡排<br />';
    }
}
class People implements JiPai
 {
   		public $XXJipai;
		function __construct()
		{
			$this->XXJipai = new XXJipai();	
		}
		function want()
		{
			$this->XXJipai->naoyou();
		}
		function cook()
		{
			$this->XXJipai->biti();
		}
 }

$test = new People();
$test->want();
$test->cook();

门面模式就是给你两个方法当门:这两个方法里面有你要执行的操作,于是你只需要调用这个门方法就可以了

门方法里面的函数是用对象调用的,对象是里面的成员属性

8 DI依赖注入

(Ioc反转控制)(Dependency Injection)

	说白了就是传递一个参数进来,只不过这个参数是强制类型
	这样就不好了,所有的全部固定了。

interface Roller
{
    function roll();
}

class MiQiLin implements Roller
{
    function roll()
    {
        echo '米其林轮胎在滚动<br />';
    }
}

class BeiNaiLi implements Roller
{
    function roll()
    {
        echo '倍耐力轮胎在滚动<br />';
    }
}
/*********************************************/
interface Runner
{
    function run();
}
class HongGuang implements Runner
{
    private $tai;
    function __construct(Roller $tai)
    {
        $this->tai = $tai;
    }
    function run()
    {
        $this->tai->roll();
        echo '神车五菱宏光在高速公路上和宝马飙车<br />';
    }
}
class BMW implements Runner
{
    private $tai;
    function __construct(Roller $tai)
    {
        $this->tai = $tai;
    }
    function run()
    {
        $this->tai->roll();
        echo '宝马在高速公路上飙车<br />';
    }
}
/*****************************************/
class Xiang
{
    private $car;
    function __construct(Runner $car)
    {
        $this->car = $car;
    }
    function travel()
    {
        $this->car->run();
        echo '我带着别人的媳妇私奔了<br />';
    }
}
//$tai = new MiQiLin();
//$tai = new BeiNaiLi();
//$car = new BMW($tai);
//$car = new HongGuang($tai);
$xiang = new Xiang(new BMW(new MiQiLin()));
$xiang->travel();

9 容器

容器:在我们的依赖注入里面需要注入大量的对象实例,然后呢,总不能全部实例化好吧,所以呢,这个时候,我们需要一个容器把这些实例放到里面,需要用的时候取出来

class Container
{
	static public $things = [];
	//往容器里面放东西
	static public function bind($name, Closure $method)		//限定类型为匿名函数
	{	
		if(!isset(self::$things[$name]))
		{
			self::$things[$name] = $method;	//这里绑定匿名函数是不执行的亲
		}
	}
	//在容器里面取出来用
	static public function make($name)
	{
		if(isset(self::$things[$name]))
		{
			$func = self::$things[$name];
			$func();
		}
	}
}
Container::bind('jinLong', function(){
	echo '你看我是两条金龙鱼<br>';
});
Container::bind('xiaojie', function(){
	echo '我要吃了哪条金龙鱼<br>';
});
Container::make('jinLong');
Container::make('xiaojie');

10 反射

主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义

通过反射机制访问对象的属性,方法,构造方法等

<?php
/**
 * 你看我是一个注释
 * @author 
 * @concat 3wfindme@gmail.com
 */
class XiaoJie
{
	public $name = 'xiaojiejie';

	/**
	 * 这是一个方法的注释
	 * @param $where string
	 * @param $how string
	 */
	public function zuo($where, $how)
	{
		echo '小杰想做于是乎他就做了。。。';
	}

	public function shui()
	{
		echo '小杰说做累了就呼呼睡觉<br>';
	}
}
// $reflection = new ReflectionClass('XiaoJie');
// $method = $reflection->getMethods();
// $doc = $reflection->getDocComment();
// var_dump($reflection->getMethod('zuo'));
// var_dump($doc);
// var_dump($method);
// var_dump($reflection);
$r = new ReflectionMethod(new XiaoJie(), 'zuo');
var_dump($r->getParameters());
var_dump($r->getDocComment());
posted @ 2017-07-07 22:23  backkom_jiu  阅读(126)  评论(0编辑  收藏  举报