学习笔记--php设计模式

设计模式简介

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

设计模式的类型

创建型模式

工厂模式(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();

——未完——

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容

  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 3,820评论 1 15
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 简单工厂模式虽然简单,但存在一个很严重的问题。当系统中需要引入新产品时,由于静态工厂方法通过所传入参数的不同来创建...
    justCode_阅读 1,136评论 1 9
  • ** 创建型设计模式 **: 单例模式(Singleton Pattern) 工厂方法模式(Factor Patt...
    刀斧手何在阅读 1,170评论 1 3
  • “富贵险中求”,这是广为流传的至理名言。大多数人只要听到有投资机会,通常人们认为就是不看准时机也要冒把险,赌一把。...
    朱坤耀阅读 139评论 0 2