学习笔记--php设计模式

2017-05-07  本文已影响0人  _______六

设计模式简介

网上有很多设计模式的介绍,也借鉴了很多。因此以下只是说自己对它的理解,若有错误之处,欢迎指出。设计模式是经过众多编程实践后,对面向对象编程总结的一些经验,不同的设计模式有不同的优势。但总的来说是为了重用代码、让代码更容易被他人理解、保证代码可靠性几个方面。由此可见,在项目中采用设计模式思维去设计代码很重要,合适的设计模式让你的项目更加规范,严谨。

设计模式的类型

创建型模式

工厂模式(Factory Pattern)

抽象工厂模式(Abstract Factory Pattern)

单例模式(Singleton Pattern)

建造者模式(Builder Pattern)

原型模式(Prototype Pattern)

这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用新的运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。

结构型模式

适配器模式(Adapter Pattern)

桥接模式(Bridge Pattern)

过滤器模式(Filter、Criteria Pattern)

组合模式(Composite Pattern)

装饰器模式(Decorator Pattern)

外观模式(Facade Pattern)

享元模式(Flyweight Pattern)

代理模式(Proxy Pattern)

这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式

行为型模式

责任链模式(Chain of Responsibility Pattern)

命令模式(Command Pattern)

解释器模式(Interpreter Pattern)

迭代器模式(Iterator Pattern)

中介者模式(Mediator Pattern)

备忘录模式(Memento Pattern)

观察者模式(Observer Pattern)

状态模式(State Pattern)

空对象模式(Null Object Pattern)

策略模式(Strategy Pattern)

模板模式(Template Pattern)

访问者模式(Visitor Pattern)

这些设计模式特别关注对象之间的通信。

常用设计模式总结

工厂模式

工厂模式是用工厂方法生成对象,而不是直接new一个对象。

假设我们在demo命名空间下有一个名叫Db的数据库操作类,用普通的方法,如果我们想去创建一个Db的对象,我们会直接new一个出来。


$db = new demo\Db();

工厂模式就是用一个工厂方法替换掉直接new一个对象的操作,以后想创建对象就调用这个工厂方法。

<?php 
namespace demo;

class Factory{
    static public function createDb(){
        $db = new Db();
        return $db;
    }
}
$db=  demo\Factory::createDb();

工厂模式有什么好处呢, 我们的项目中多处都对Db类进行了new的操作,如果这个类发生了一些更改,比如说类名或者是参数的改变,没用工厂模式的话我们就需要进行多处更改,而工厂模式只需要改这个工厂类就行了。很多其他设计模式也是依赖于工厂模式的。

单例模式

单例模式使某个类的对象仅能创建一次,通常一个项目中会多次用的Db这个数据库连接类,如果在每个地方都调用工厂方法创建一个数据库连接类,这样是比较消耗资源的,我们只需要一个数据库连接,单例模式就是来解决这个问题的。

我们打开Db类,首先把构造方法设置为私有的,这样就禁止了在其他地方直接new我们的Db类

<?php 
namespace demo;

class Db{
    protected $db;
    private function __construct(){

    }
    static public function getInstance(){
        //条件判断Db类是否已经new过
        if (self::$db) {
            return self::$db;
        } else {
            //构造方法被设置为了私有的,外部不能直接new,但自己内部可以new
            self::$db = new self();
            return self::$db;
        }
    }

//下面省略一系列操作数据库的方法
}

Db类的构造方法设置为了私有的,那我们在工厂类中也不能直接new了,现在来修改我们的工厂类

<?php 
namespace demo;

class Factory{
    static public function createDb(){
        $db = Db::getInstance;
        return $db;
    }
}

现在不管我们调用多少次工厂方法,我们的数据库连接都只会被创建一次。

注册树模式

注册树模式可以把我们的对象放在全局的树上,让对象可以全局共享

下面我们来编写一个注册树的类,包含set,get,_unset三个操作。

<?php 
namespace demo;

class Register{
    protected static $objects;
    static public function set($alias,$object){
        self::$objedts[$alias] = $object;
    }

    static public function get($name){
        return self::$objedts[$name];
    }

    //unset是php中的关键词,所以起名为_unset,移除对象
    static public function _unset($alias){
        unset(self::$objedts[$alias]);
    }
}

下面我们再把工厂方法改一下

<?php 
namespace demo;

class Factory{
    static public function createDb(){
        $db = Db::getInstance;
        //把单例模式生成的对象放在注册树上
        Register::set('db',$db);
    }
}

现在这个工厂方法只需要调用一次,以后再需要使用数据库连接对象,直接从全局的注册树上拿就行了

 $db = Register::get("db");

至于这个工厂方法是么时候调用,可以在程序初始化的时候,我们的业务逻辑代码只需要在注册树上把这个对象读取出来即可。

适配器模式

适配器模式可以将截然不同的函数接口封装成统一的API。例如,PHP的数据库操作有mysql,mysqli,pdo 三种,可以用适配器模式统一成一致。类似的场景还有cache适配器,将memcache,redis,file,apc等不同的缓存函数,统一成一致。

下面还是以数据库操作为例。
首先定义数据库接口。

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

接下来编写不同的数据库类,使它们变成一样的接口。
这里主要讲mysqli和pdo两个

<?php
namespace demo\Database;

use demo\IDatabase;
class MySQLi implements IDatabase
{
    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 demo\Database;

use demo\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);
    }
}

外部调用

//通过改变实例化对象即可实现切换
//$db = new demo\Database\PDO();

$db = new demo\Database\MySQLi();
$db->connect('127.0.0.1','root','root','test');
$db->query("show databases");
$db->close();

策略模式

首先声明一个策略的接口文件,它约定了策略有哪些行为。

<?php
interface UserStrategy {
    //约定了两个方法
    function showAd();//显示广告
    function showCategory();//显示一个类目
}

再来定义具体的策略文件
女性用户

class FemaleUserStrategy implements UserStrategy {
    function showAd()
    {
        echo "热门女装";
    }
    function showCategory()
    {
        echo "女装";
    }
}

男性用户

class MaleUserStrategy implements UserStrategy {
    function showAd()
    {
        echo "热门手机";
    }
    function showCategory()
    {
        echo "电子产品";
    }
}

页面
class Page
{
protected $strategy;
function index()
{
echo "AD:";
$this->strategy->showAd();

    echo "Category";
    $this->strategy->showCategory();
}
function setStrategy(\demo\UserStrategy $strategy)
{
    $this->strategy = $strategy;
}

}
$page = new Page;
if (isset($_GET['female'])){
$strategy = new \demo\FemaleUserStrategy();
} else {
$strategy = new \demo\MaleUserStrategy();
}
$page->setStrategy($strategy);
$page->index();

——未完——

上一篇下一篇

猜你喜欢

热点阅读