PHP设计模式

目录

一、使用设计模式目的

二、设计模式的七大原则

三、创建型模式(构建型模式)

1、单例模式

代码实例

2、工厂模式

2.1、工厂模式——简单工厂模式

简单工厂模式的代码实例

2.2、工厂模式——工厂方法模式

工厂方法模式的代码实例

 2.3、工厂模式——抽象工厂模式

3、原型模式

原型模式的代码实例

浅拷贝

深拷贝

4、建造者模式

四、结构型模式

适配器模式

桥接模式

装饰模式

组合模式

外观模式

享元模式

代理模式

五、行为型模式

模版方法模式

命令模式

访问者模式

迭代器模式(Iterator)(生成器模式(generator)是迭代器的一种,即迭代器的实现)

观察者模式

中介者模式

备忘录模式、

解释器模式(Interpreter)

状态模式

策略模式

职责链模式(责任链模式)


一、使用设计模式目的

  1. 重用性 (相同功能的代码,不用多次编写)
  2. 可读性 (编程规范性, 便于其他程序员的阅读和理解)
  3. 可扩展性 (当需要增加新的功能时,非常的方便,称为可维护)
  4. 可靠性 (当我们增加新的功能后,对原来的功能没有影响)
  5. 使程序呈现高内聚,低耦合的特性

二、设计模式的七大原则

  1. 单一职责原则:一个类应该只负责一项职责
  2. 接口隔离原则:一个类对另一个类的依赖应该建立在最小的接口上。客户端不应该依赖它不需要的接口
  3. 依赖倒转(倒置)原则:对抽象进行编程,不要对实现进行编程。程序要依赖于抽象接口,不要依赖于具体实现
  4. 里氏替换原则:子类可以扩展父类的功能,但不能改变原有父类的功能
  5. 开闭原则:又叫开放封闭原则。对扩展开发,对修改关闭
  6. 迪米特法则:又叫最少知识原则。一个类对于其他类知道的越少越好
  7. 合成复用原则:又叫组合/聚合复用原则。通过将已有的对象纳入新对象中,作为新对象的成员对象来实现的,新对象可以调用已有对象的功能,从而达到复用。软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现

三、创建型模式(构建型模式)

  • 1、单例模式

 

单例模式的主要特点是【三私一公】

  1.  私有的静态成员变量(用来保存类的唯一实例)
  2.  私有的构造函数,防止外部程序new一个对象从而失去单例的意义
  3.  私有的克隆函数,防止对象被克隆
  4.  公共的静态方法(通常命名为getInstance),从而返回唯一实例的一个引用。

代码实例

<?php

namespace App\Services;

class DanLiService
{
    private static $instance = null;

    private function __construct()
    {
    }

    private function __clone()
    {
        // TODO: Implement __clone() method.
    }

    public static function getInstance()
    {
        if(empty( self::$instance )){
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function testOne()
    {
        return '实现1';
    }

    public function testTwo()
    {
        return '实现2';
    }

}

$obj = DanLiService::getInstance();
print_r($obj->testOne());
print_r($obj->testTwo());

2、工厂模式

        工厂模式一共分3三种:简单工厂模式、工厂方法模式、抽象工厂模式

        在平时写代码过程中,构建对象最常用的方式是 new 一个对象。这属于一种硬编码。每 new 一个对象,相当于调用者就知道了一个类,增加了类与类之间的联系,不利于程序的松耦合。其实构建过程可以被封装起来,工厂模式便是用于封装对象的设计模式。

  • 2.1、工厂模式——简单工厂模式

例如:

        当我们需要一个苹果时,我们需要知道苹果的构造方法,需要一个梨子时,需要知道梨子的构造方法。

        更好的实现方式是有一个水果工厂,我们告诉工厂需要什么种类的水果,水果工厂将我们需要的水果制造出来给我们就可以了。这样我们就无需知道苹果、梨子是怎么种出来的,只用和水果工厂打交道即可。

  • 简单工厂模式的代码实例

/**
 * 水果工厂类
 */
class FruitFactory
{
    /**
     * 通知不同水果的生产车间
     * @param string    $name   [车间名字]
     * @return object
     */
    public static function noticeWorkShop( $name )
    {
        switch($name){
            //苹果
            case 'apple':
                return new Apple();
            //梨
            case 'pear':
                return new Pear();
            default:
                throw new \Exception( '抱歉!我们工厂不生产该种类水果。' );
        }
    }
}

/**
 * 苹果车间
 */

class Apple implements Product
{
    public function __construct()
    {
    }

    public function eat()
    {
        // TODO: Implement sound() method.
        echo '我是苹果';
    }
}

/**
 * 梨车间
 */

class Pear implements Product
{
    public function __construct()
    {
    }

    public function eat()
    {
        // TODO: Implement sound() method.
        echo '我是梨';
    }
}


/**
 * 水果产品接口类,该类中定义的方法,都是子类所必须实现的方法
 */
interface Product
{
    /**
     * @return mixed
     */
    public function eat();
}

//调用实例
try{
  $product = FruitFactory::noticeWorkShop('apple');
  $obj = $product->eat();
  print_r($obj);die;
}catch(\Exception $e) {
  echo $e->getMessage();
}
  • 2.2、工厂模式——工厂方法模式

工厂方法模式是简单工厂的升级版,在原有的基础上对工厂进行一个抽象的升级,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。

  • 工厂方法模式的代码实例

/**
 * 苹果工厂类,专门负责加工苹果
 */

class AppleFactory
{
    public function __construct()
    {
    }

    public function create(){
        return new Apple();
    }
}


/**
 * 梨工厂,专门负责加工梨
 */

class PearFactory
{
    public function __construct()
    {
    }

    public function create()
    {
        return new Pear();
    }
}

//调用实例
try{
    //调用苹果工厂
    $appleFactory = new AppleFactory();
    $appleObj = $appleFactory->create();
    $appleObj->eat();
    //调用梨工厂
    $pearFactory = new PearFactory();
    $pearObj = $pearFactory->create();
    $pearObj->eat();
    die;
}catch(\Exception $e) {
  echo $e->getMessage();
}

        有没有发现上述代码和直接 new 出Apple对象和Pear对象有什么区别?感觉上没什么区别。不过上文提到了工厂是为了减少类与类之间的耦合,让调用者尽可能少的和其他类打交道。用简单工厂模式,我们只需要知道 FruitFactory,无需知道 Apple 、Pear 类,很容易看出耦合度降低了。但用工厂方法模式,调用者虽然不需要和 Apple 、Pear 类打交道了,但却需要和 AppleFactory、PearFactory 类打交道。有几种水果就需要知道几个工厂类,耦合度完全没有下降,甚至还增加了代码量!

        还是有些优点的:

  1. 当某个产品构建相当复杂时,工厂将构建过程封装起来,调用者可以很方便的使用。
  2. 当生产的水果产品越来越多时,工厂类不会变成超级类,工厂类会越来越多,但不会越来越大,不会变得臃肿,这就符合【单一职责原则】
  •  2.3、工厂模式——抽象工厂模式

抽象工厂模式:是工厂方法模式的进一步优化 

/**
 * 抽象工厂接口
 */
interface InterfaceFactory
{
    /**
     * @return mixed
     */
    public function create();
}
/**
 * 苹果工厂类,继承工厂接口
 */

class AppleFactory implements InterfaceFactory
{
    public function create(){
        return new Apple();
    }
}

/**
 * 梨工厂类,继承工厂接口
 */

class PearFactory implements InterfaceFactory
{

    public function create()
    {
        return new Pear();
    }
}

此时,调用者可以将 AppleFactory 和 PearFactory 统一作为 InterfaceFactory 对象使用

//调用者
try{
    $appleFactory = new AppleFactory();
    $objApple = $appleFactory->create();
    $objApple->eat();
}catch(\Exception $e) {
    echo $e->getMessage();
}
  1.  由于客户端只和 InterfaceFactory 打交道了,调用的是接口中的方法,使用时根本不需要知道是在哪个具体工厂中实现的这些方法,这就使得替换工厂变得非常容易。
  2. 抽象工厂模式很好的发挥了开闭原则、依赖倒置原则,但缺点是抽象工厂模式太重了,如果 InterfaceFactory 接口需要新增功能,则会影响到所有的具体工厂类。使用抽象工厂模式,替换具体工厂时只需更改一行代码,但要新增抽象方法则需要修改所有的具体工厂类。所以抽象工厂模式适用于增加同类工厂这样的横向扩展需求,不适合新增功能这样的纵向扩展。

3、原型模式

  • 原型模式(Prototype Pattern):与工厂模式类似,都是用来创建对象的。原型模式是利用克隆来生成一个大对象,减少创建(new)时的初始化等操作占用开销,原型模式仅需内存拷贝
  • 为什么需要原型模式?
  1. 有些时候,我们需要创建多个类似的大对象。如果直接通过new对象,开销很大,而且new完还得进行重复的初始化工作。可能把初始化工作封装起来的,但是对于系统来说,你封不封装,初始化工作还是要执行。
  2. 原型模式则不同,原型模式是先创建好一个原型对象,然后通过clone这个原型对象来创建新的对象,这样就免去了重复的初始化工作,系统仅需内存拷贝即可。
  • 原型模式的代码实例

定义一个原型接口 

interface Prototype{
    //浅拷贝
    public function shallowCopy();

    //深拷贝
    public function deepCopy();
}

定义一个具体原型

class ConcretePrototype implements Prototype
{
    private $_name;
    public function __construct($name)
    {
        $this->_name = $name;
    }

    public function setName($name)
    {
        $this->_name = $name;
    }
    public function getName()
    {
        return $this->_name;
    }


    //浅拷贝
    public function shallowCopy()
    {
        // TODO: Implement shallowCopy() method.
        return clone $this;
    }

    //深拷贝
    public function deepCopy()
    {
        // TODO: Implement deepCopy() method.
        $serializeObj = serialize($this);
        $cloneObj = unserialize($serializeObj);
        return clone $cloneObj;
    }

}

定义一个用户测试原型

class Demo{
    public $string;
}

class UserPrototype
{
    //浅拷贝
    public function shallow()
    {
        $demo = new Demo();
        $demo->string = "susan";

        $object_shallow_first = new ConcretePrototype($demo);
        $object_shallow_second = $object_shallow_first->shallowCopy();


        var_dump($object_shallow_first->getName());
        echo '<br/>';
        var_dump($object_shallow_second->getName());
        echo '<br/>';

        $demo->string = "sacha";
        var_dump($object_shallow_first->getName());
        echo '<br/>';
        var_dump($object_shallow_second->getName());
        echo '<br/>';

    }

    //深拷贝
    public function deep()
    {
        $demo = new Demo();
        $demo->string = "Siri";

        $object_deep_first = new ConcretePrototype($demo);
        $object_deep_second = $object_deep_first->deepCopy();

        var_dump($object_deep_first->getName());
        echo '<br/>';
        var_dump($object_deep_second->getName());
        echo '<br/>';

        $demo->string = "Demo";
        var_dump($object_deep_first->getName());
        echo '<br/>';
        var_dump($object_deep_second->getName());
        echo '<br/>';

    }
}

调用

try{
    $user = new UserPrototype();
    $user->shallow();
    echo "</BR>";
    $user->deep();;
}catch(\Exception $e) {
    echo $e->getMessage();
}

调用测试结果

object(App\Services\Demo)#1229 (1) { ["string"]=> string(5) "susan" }
object(App\Services\Demo)#1229 (1) { ["string"]=> string(5) "susan" }
object(App\Services\Demo)#1229 (1) { ["string"]=> string(5) "sacha" }
object(App\Services\Demo)#1229 (1) { ["string"]=> string(5) "sacha" }

object(App\Services\Demo)#1236 (1) { ["string"]=> string(4) "Siri" }
object(App\Services\Demo)#1237 (1) { ["string"]=> string(4) "Siri" }
object(App\Services\Demo)#1236 (1) { ["string"]=> string(4) "Demo" }
object(App\Services\Demo)#1237 (1) { ["string"]=> string(4) "Siri" }

浅拷贝

赋值时引用赋值,相当于取了一个别名。对其中一个修改,会影响另一个, 对象作为参数传递时,也是引用传递 

深拷贝

赋值时值完全复制,完全的copy,对其中一个作出改变,不会影响另一个

4、建造者模式

核心思想是将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式

/**
 * 抽象接口
 */
interface InterfaceBuilder
{
    //创建车辆
    public function createVehicle();

    //添加车门
    public function addDoors();

    //添加引擎
    public function addEngine();

    //添加车轮
    public function addWheel();

    //获取车辆
    public function getVehicle();

}

 实现所有方法的自行车类

class BikeBuilder implements InterfaceBuilder
{
    protected $bike;

    public function createVehicle()
    {
        $this->bike[] = '创建自行车建造任务';
    }

    public function addDoors()
    {
        $this->bike[] = '建造了车门';
    }

    public function addEngine()
    {
        $this->bike[] = null;
    }

    public function addWheel()
    {
        $this->bike[] = '建造了车轮';
    }

    public function getVehicle()
    {
       return $this->bike;
    }
}

 实现所有方法的轿车类

class CarBuilder implements InterfaceBuilder
{
    protected $car;

    public function createVehicle()
    {
        $this->car[] = '创建小轿车建造任务';
    }

    public function addDoors()
    {
        $this->car[] = '建造了车门';
    }

    public function addEngine()
    {
        $this->car[] = '建造了引擎发动机';
    }

    public function addWheel()
    {
        $this->car[] = '建造了车轮';
    }

    public function getVehicle()
    {
        return $this->car;
    }
}

 按照实际需要,分别调用Bike类和Car类,实现所有功能聚合

class Index
{
    public $vecicle;

    public function getVe($type = 1)
    {
        if ($type == 1) { //Bike
            $this->vecicle = new BikeBuilder();
        } else if ($type == 2) { //Car
            $this->vecicle = new CarBuilder();
        }
        $this->vecicle->createVehicle();
        $this->vecicle->addDoors();
        $this->vecicle->addEngine();
        $this->vecicle->addWheel();
        $this->vecicle->getVehicle();

        return $this->vecicle;
    }

}

四、结构型模式

  • 适配器模式

  • 桥接模式

  • 装饰模式

  • 组合模式

  • 外观模式

  • 享元模式

  • 代理模式

五、行为型模式

  • 模版方法模式

  • 命令模式

  • 访问者模式

  • 迭代器模式(Iterator)(生成器模式(generator)是迭代器的一种,即迭代器的实现)

  • 观察者模式

  • 中介者模式

  • 备忘录模式、

  • 解释器模式(Interpreter)

  • 状态模式

  • 策略模式

  • 职责链模式(责任链模式)
     

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值