设计模式

# 设计模式  老程序员 整理  经常遇到的问题  一些通用解决方案

单例模式:

三私一公

  1. _instance必须声明为静态的私有变量
  2. 构造函数和析构函数必须声明为私有,防止外部程序new 类从而失去单例模式的意义
  3. getInstance()方法必须设置为公有的,必须调用此方法 以返回实例的一个引用
  4. ::操作符只能访问静态变量和静态函数
  5. new对象都会消耗内存
  6. 使用场景:最常用的地方是数据库连接,系统配置。
  7. 使用单例模式生成一个对象后, 该对象可以被其它众多对象所使用。
  8. 私有的__clone()方法防止克隆对象

单例模式,使某个类的对象仅允许创建一个。构造函数private修饰, 
申明一个static getInstance方法,在该方法里创建该对象的实例。如果该实例已经存在,则不创建。比如只需要创建一个数据库连接。

<?php
class Explame {
    private  static $intance;
    private  function __construct()
    {
        echo "aa";
    }
    public static function getInstance()
    {
        if (!isset(self::$intance)){
            $c = __CLASS__;
            self::$intance = new $c;
        }
        return self::$intance;
    }
    private function __clone()
    {
        // TODO: Implement __clone() method.
        trigger_error('错误',E_USER_ERROR);
    }
    public function  test(){
        echo '单例';
    }

}
?>

工厂模式

工厂模式,工厂方法或者类生成对象,而不是在代码中直接new。 
使用工厂模式,可以避免当改变某个类的名字或者方法之后,在调用这个类的所有的代码中都修改它的名字或者参数。

## 工厂模式

namespace factory;
/**
 * 需要短信发送组件   有两种接口   1、阿里云   2、56短信
 * @author jack
 */
abstract class Message {

    abstract public function send($mobile,$message);
}
Class Alidayu extends Message
{
    public function send($mobile,$message){}
}
Class SMS56 extends Message
{
    public function send($mobile,$message){}
}


####################################################


$rest = (new Alidayu())->send('18612345698','xxxxx');
# 问题 我项目当中有50多处 都发送了短信  1/工作量巨大   2、测试工作量也大

/**
 * @author Jack
 */
class MessageFactory
{
    protected static $msgType = [
        'alidayu' => 'Alidayu',
        '56'      => 'SMS56'
    ];

    /**
     * 生成对象
     * @param string $name
     * @throws \Exception
     * @return Object
     */
    public static function createMessage( $name )
    {
        if (! array_key_exists($name, self::msgType)) {
            throw new \Exception("$name not exist");
        }
        $className = self::msgType[$name];
        return new $className();
    }
}


$rest = MessageFactory::createMessage('alidayu')->send('18612345678','xxxxx');

观察者模式

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

<?
# 被观察者接口
interface Observable{
    public function addObserver($ob);//添加观察者
    public function delObserver($ob);//删除观察者
    public function event();//被观察事件
}

# 观察者接口
interface Observer{
    public function Response();
}

# 被观察者:小明刷卡
Class Sk implements Observable
{
    protected $observer = [];
    public function addObserver($ob)
    {
        if(!in_array($ob,$this->observer)){
            $this->observer[] = $ob;
        }
    }
    public function delObserver($ob)
    {
        // TODO: Implement delObserver() method.
    }
    public function event()
    {
        foreach ($this->observer as $ob){
            $ob->Response();
            echo '<hr>';
        }
    }
}

# 观察者:老妈
class Mom implements Observer
{
    public function Response()
    {
        echo "老妈就电话给他 叫他别乱花钱,要什么东西妈给买";
    }
}
# 观察者:女友
class GirlFriend implements Observer
{
    public function Response()
    {
        echo "女友:赶紧带着我的限量款口红回来";
    }
}
# 观察者:姐姐
class Sister implements Observer
{
    public function Response()
    {
        echo "姐姐:给我买了没有";
    }
}

$sk = new Sk();

$sk->addObserver(new Mom());
$sk->addObserver(new GirlFriend());
$sk->addObserver(new Sister());

$sk->event();



?>

策略模式

策略模式,将一组特定的行为和算法封装成类,以适应某些特定的上下文环境。 
eg:假如有一个电商网站系统,针对男性女性用户要各自跳转到不同的商品类目,并且所有的广告位展示不同的广告。在传统的代码中,都是在系统中加入各种if else的判断,硬编码的方式。如果有一天增加了一种用户,就需要改写代码。使用策略模式,如果新增加一种用户类型,只需要增加一种策略就可以。其他所有的地方只需要使用不同的策略就可以。 
首先声明策略的接口文件,约定了策略的包含的行为。然后,定义各个具体的策略实现类。

UserStrategy.php
<?php
/*
 * 声明策略文件的接口,约定策略包含的行为。
 */
interface UserStrategy
{
    function showAd();
    function showCategory();
}
FemaleUser.php
<?php
require_once 'Loader.php';
class FemaleUser implements UserStrategy
{
    function showAd(){
        echo "2016冬季女装";
    }
    function showCategory(){
        echo "女装";
    }
}
MaleUser.php
<?php
require_once 'Loader.php';
class MaleUser implements UserStrategy
{
    function showAd(){
        echo "IPhone6s";
    }
    function showCategory(){
        echo "电子产品";
    }
}
Page.php//执行文件
<?php
require_once 'Loader.php';
class Page
{
    protected $strategy;
    function index(){
        echo "AD";
        $this->strategy->showAd();
        echo "<br>";
        echo "Category";
        $this->strategy->showCategory();
        echo "<br>";
    }
    function setStrategy(UserStrategy $strategy){
        $this->strategy=$strategy;
    }
}

$page = new Page();
if(isset($_GET['male'])){
    $strategy = new MaleUser();
}else {
    $strategy = new FemaleUser();
}
$page->setStrategy($strategy);
$page->index();

适配器模式

将各种截然不同的函数接口封装成统一的API。 
PHP中的数据库操作有MySQL,MySQLi,PDO三种,可以用适配器模式统一成一致,使不同的数据库操作,统一成一样的API。类似的场景还有cache适配器,可以将memcache,redis,file,apc等不同的缓存函数,统一成一致。 
首先定义一个接口(有几个方法,以及相应的参数)。然后,有几种不同的情况,就写几个类实现该接口。将完成相似功能的函数,统一成一致的方法。

1 接口 IDatabase
2 <?php
3 namespace IMooc;
4 interface IDatabase
5 {
6     function connect($host, $user, $passwd, $dbname);
7     function query($sql);
8     function close();
9 }
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差异带来的环境改变之后需要改写代码的问题。

 
上一篇:Lambda表达式类型检查


下一篇:【笔记】云原生华为直播课