PHP开发中常用的设计模式


什么是设计模式

典型场景 -> 典型问题 -> 典型解决方案

高内聚低耦合,代码更易于使用

多态

在面向对象中,指某种对象实例的不同表现形态。

多态的特点在静态语言中比较明显,而对于PHP这种动态语言,很多场景就被天然消除了。所以,在PHP中不可生搬硬套Java或者C++的设计模式。

工厂模式

  • 工厂模式可以将对象的生产从直接new一个对象,改成通过调用一个工厂方法生产。这样的封装,代码若需修改new的对象时,不需修改多处new语句,只需更改生产对象方法。
  • 根据抽象程度不同,工厂模式分为:简单工厂模式、工厂方法模式和抽象工厂模式。

简单工厂

  • 简单工厂又叫静态工厂方法模式,这样理解可以确定,简单工厂模式是通过一个静态方法创建对象的。
  • 缺点:当产品修改时,工厂类也要做相应的修改,违反了开-闭原则(对修改关闭-对拓展开放)。
interface  people {
    function  jiehun();
}
class man implements people{
    function jiehun() {
        echo '送玫瑰,送戒指!<br>';
    }
}
  
class women implements people {
    function jiehun() {
        echo '穿婚纱!<br>';
    }
}
  
class SimpleFactoty {
    // 简单工厂里的静态方法
    static function createMan() {
        return new     man;
    }
    static function createWomen() {
        return new     women;
    }
     
}
  
$man = SimpleFactoty::createMan();
$man->jiehun();
$man = SimpleFactoty::createWomen();
$man->jiehun();

工厂方法模式

  • 定义一个创建对象的接口,让子类决定哪个类实例化。 他可以解决简单工厂模式中的封闭开放原则问题。
interface  people {
    function  jiehun();
}
class man implements people{
    function jiehun() {
        echo '送玫瑰,送戒指!<br>';
    }
}
  
class women implements people {
    function jiehun() {
        echo '穿婚纱!<br>';
    }
}
  
interface  createMan {  // 注意了,这里是简单工厂本质区别所在,将对象的创建抽象成一个接口。
    function create();
  
}
class FactoryMan implements createMan{
    function create() {
        return  new man;
    }
}
class FactoryWomen implements createMan {
    function create() {
        return new women;
    }
}
  
class  Client {
    // 简单工厂里的静态方法
    function test() {
        $Factory =  new  FactoryMan;
        $man = $Factory->create();
        $man->jiehun();
         
        $Factory =  new  FactoryWomen;
        $man = $Factory->create();
        $man->jiehun();
    }
}
  
$f = new Client;
$f->test();

抽象工厂模式

  • 抽象工厂:提供一个创建一系列相关或相互依赖对象的接口。
  • 注意:这里和工厂方法的区别是:一系列,而工厂方法则是一个。
interface  people {
    function  jiehun();
}
class Oman implements people{
    function jiehun() {
        echo '美女,我送你玫瑰和戒指!<br>';
    }
}
class Iman implements people{
    function jiehun() {
        echo '我偷偷喜欢你<br>';
    }
}
  
class Owomen implements people {
    function jiehun() {
        echo '我要穿婚纱!<br>';
    }
}
  
class Iwomen implements people {
    function jiehun() {
        echo '我好害羞哦!!<br>';
    }
}
  
interface  createMan {  // 注意了,这里是本质区别所在,将对象的创建抽象成一个接口。
    function createOpen(); //分为 内敛的和外向的
    function createIntro(); //内向
  
}
class FactoryMan implements createMan{
    function createOpen() {
        return  new  Oman;
    }
    function createIntro() {
        return  new Iman;
    }
}
class FactoryWomen implements createMan {
    function createOpen() {
        return  new  Owomen;
    }
    function createIntro() {
        return  new Iwomen;
    }
}
  
class  Client {
    // 简单工厂里的静态方法
    function test() {
        $Factory =  new  FactoryMan;
        $man = $Factory->createOpen();
        $man->jiehun();
         
        $man = $Factory->createIntro();
        $man->jiehun();
         
         
        $Factory =  new  FactoryWomen;
        $man = $Factory->createOpen();
        $man->jiehun();
         
        $man = $Factory->createIntro();
        $man->jiehun();
         
    }
}
  
$f = new Client;
$f->test();

区别

  • 简单工厂模式:用来生产同一等级结构中的任意产品。对与增加新的产品,无能为力。
  • 工厂模式 :用来生产同一等级结构中的固定产品。(支持增加任意产品)
  • 抽象工厂 :用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)

以上三种工厂 方法在等级结构和产品族这两个方向上的支持程度不同。所以要根据情况考虑应该使用哪种方法

适用范围

  • 简单工厂模式:工厂类负责创建的对象较少,客户只知道传入工厂类的参数,对于如何创建对象不关心。
  • 工厂方法模式:当一个类不知道它所必须创建对象的类或一个类希望由子类来指定它所创建的对象时,当类将创建对象的职责委托给多个帮助子类中得某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候,可以使用工厂方法模式
  • 抽象工厂模式:一个系统不应当依赖于产品类实例何如被创建,组合和表达的细节,这对于所有形态的工厂模式都是重要的。这个系统有多于一个的产品族,而系统只消费其 中某一产品族。同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。系统提供一个产品类的库,所有的产品以同样的接口出现,从 而使客户端不依赖于实现。

无论是简单工厂模式、工厂模式还是抽象工厂模式,它们本质上都是将不变的部分提取出来,将可变的部分留作接口,以达到最大程度上的复用。究竟用哪种设计模式更适合,这要根据具体的业务需求来决定。

单例模式

  • 整个应用中只有一个实例对象的设计模式
  • 应用:php中的应用主要在于数据库操作, 一个应用中会存在大量的数据库操作,使用单例模式, 则可以避免大量的new 操作消耗的资源。
class Singleton{
    //私有属性,用于保存实例
    private static $instance;
    //构造方法私有化,防止外部创建实例
    private function __construct(){}
    //公有属性,用于测试
    public $a;
    //公有方法,用于获取实例
    public static function getInstance(){
        //判断实例有无创建,没有的话创建实例并返回,有的话直接返回
        if(!(self::$instance instanceof self)){
            self::$instance = new self();
        }
        return self::$instance;
    }
    //克隆方法私有化,防止复制实例
    private function __clone(){}

}

观察者模式

  • 从面向过程的角度来看,首先是观察者向主题注册,注册完之后,主题再通知观察者做出相应的操作,整个事情就完了。
  • 从面向对象的角度来看,主题提供注册和通知的接口,观察者提供自身操作的接口。(这些观察者拥有一个同一个接口。)观察者利用主题的接口向主题注册,而主题利用观察者接口通知观察者。耦合度相当之低。

责任链模式

  • 又叫职责链模式。建立一个对象链,按照指定顺序处理调用;如果其中有一个对象无法处理当前的情况,移交下一个对象处理。
//示例:当处理一个帖子时,
//如果不文明严重程度处理
//1级,版主删帖
//2级,管理员封账号
//3级,治安部门管理

//版主
class board{
    protected $level = 1;//当前级别为1
    protected $top = 'admin';//高一级的处理

    public function process($lv=1){
        if($lv <= $this->level){
            echo '版主删帖' . '<br/>';
        }else{
            $topCls = new $this->top;
            $topCls->process($lv);
        }
    }
}

//管理员
class admin{
    protected $level = 2;//当前级别为2
    protected $top = 'police';//高一级的处理

    public function process($lv=2){
        if($lv <= $this->level){
            echo '管理员冻结登录账号' . '<br/>';
        }else{
            $topCls = new $this->top;
            $topCls->process($lv);
        }
    }
}


//治安部门
class police{
    public function process($lv=3){
        echo '治安部门参与治理' . '<br/>';
    }
}


$lv = isset($_GET['lv'])?$_GET['lv']:1;

$cls = new board();
$cls->process($lv);

策略模式

  • 定义一系列的算法,把每一个算法封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。是一种行为模式。

装饰器模式

  • 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
  • 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
  • 我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。
  • 优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
  • 缺点:多层装饰比较复杂。

适配器模式

  • 适配器模式(Adapter)模式:将一个类的接口,转换成客户期望的另一个类的接口。适配器让原本接口不兼容的类可以合作无间。

桥接模式

  • 将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

本文发表于2020年09月09日 17:52
阅读 238 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

一直到现在我才突然明白,我梦寐以求,是真爱和自由。

把爱情留给我身边最真心的姑娘,你陪我歌唱陪我流浪,陪我两败俱伤。

把青春献给身后那座辉煌的都市,为了这个美梦,我们付出着代价。

又是一年五一,祝我们工人阶级劳动节快乐! 今年被困在北京了,离境再入境需要隔离十五天。只能京津冀周边走一走了,想出去玩啊啊啊啊啊~

人活一辈子,不是一年两年。时间是有连续性的,做抉择的时候要多看几步。保持警惕,大丈夫有所为,有所不为。

快捷链接
网站地图
提交友链
Copyright © 2016 - 2020 Cion.
All Rights Reserved.
ICP备案:鲁ICP备19012333号-4.

鲁公网安备 37061302000383号.