博客列表 >设计模式与服务容器-2019年12月5日

设计模式与服务容器-2019年12月5日

古城老巷丶
古城老巷丶原创
2019年12月08日 21:17:00784浏览

1. 将课堂代码全部上机操作至少一遍以上。

单列模式:

实例

<?php

namespace _1205;

use PDO;
// 单列模式
class Temp
{
    //
}

$obj1 = new Temp();
$obj2 = new Temp();
var_dump($obj1, $obj2);
echo '<br>';
var_dump($obj1 === $obj2);
echo '<hr>';

// 单列模式原理
class Demo1
{
    // 不让外部实例化操作,将构造方法私有化
    private function __construct()
    {
    }

    // 目前只能在类的内部进行实例化该类
    // 在不能实例化的情况下,我们只能使用类来访问,用类来访问类中成员必须是静态成员。
    // 因此,需要插件两个静态成员
    // 第一个静态成员,是当前类的实例
    public static $instance = null;

    // 第二个静态成员,是实例化当前类的方法
    public static function getInstance()
    {
        // 作用:实例化当前类,并且返回实例/对象
        /**
         * 分两步
         * 1.判断当前类是否被实例化过了。如果没有被实例化,就实例化该类。如果已实例化,就返回即可。
         */
        if (is_null(self::$instance)) {
            //如果没有实例化,则实例化该类并保存到$instance静态属性里
            self::$instance = new self(); //$instance是静态属性,所以需要self调用
        }
        // 如果已经实例化该类,则返回它
        return self::$instance;
    }

    // 禁用克隆方法,保证该类有唯一实例。
    private function __clone()
    {
        // TODO: Implement __clone() method.
    }
}


// 测试
//通过类访问静态方法getInstance(),
$obj1 = Demo1::getInstance();
$obj2 = Demo1::getInstance();
echo '<br>';
var_dump($obj1 === $obj2);
echo '<hr>';

// 单列模式应用场景
class Db
{
    // 不让外部实例化操作,将构造方法私有化
    // 构造方法接受参数,因为构造方法每次都默认调用,所以接收参数来实现屎壳郎连接。
    private function __construct(...$connect)
    {
        //将构造方法接收的数据提取出来
        $dsn = $connect[0];
        $username = $connect[1];
        $password = $connect[2];

        //创建Pdo实例
        self::$pdo = new \PDO($dsn, $username, $password);
    }

    // 目前只能在类的内部进行实例化该类
    // 在不能实例化的情况下,我们只能使用类来访问,用类来访问类中成员必须是静态成员。
    // 因此,需要插件两个静态成员
    // 第一个静态成员,是当前类的实例
    public static $pdo = null;

    // 第二个静态成员,是实例化当前类的方法
    //接受外部传入参数
    public static function getInstance(...$connect)
    {
        // 作用:实例化当前类,并且返回实例/对象
        /**
         * 分两步
         * 1.判断当前类是否被实例化过了。如果没有被实例化,就实例化该类。如果已实例化,就返回即可。
         */
        if (is_null(self::$pdo)) {
            //如果没有实例化,则实例化该类并保存到$instance静态属性里
            //创建实例化时添加参数。
           // 构造函数不需要返回
           new self(...$connect); //
        }
        // 如果已经实例化该类,则返回它
        return self::$pdo;
    }

    // 禁用克隆方法,保证该类有唯一实例。
    private function __clone()
    {
        // TODO: Implement __clone() method.
    }
}

//连接数据库参数
$connect = ['mysql:host=localhost;dbname=test', 'root', 'root'];
//创建连接对象
$pdo = Db::getInstance(...$connect);
echo '<hr>';
$sql = $pdo->query('select * from goods');
echo '<pre>';
print_r($sql->fetchAll());
echo '<pre>';
image.png

 工厂模式:

 

实例

<?php

namespace _1205;

// 工厂模式;用于批量创建类的实例或对象,

class Test1
{
    public function __construct($arg1)
    {
        // 输出
        echo '对象创建成功,参数是:' . $arg1 . '<br>';
    }
}

class Test2
{
    public function __construct($arg1, $arg2)
    {
        // 输出
        echo '对象创建成功,参数是:' . implode(',', [$arg1, $arg2]) . '<br>';
    }
}

class Test3
{
    public function __construct($arg1, $arg2, $arg3)
    {
        // 输出
        echo '对象创建成功,参数是:' . implode(',', [$arg1, $arg2, $arg3]) . '<br>';
    }
}

// 创建工厂类,专用批量创建类实例、对象
class Factory
{
    /**
     * 专用实例化类
     * 参数1:类的名称
     * 参数2:构造方法的参数
     * @param $className
     * @param array $arg
     * @return mixed
     */
    public static function create($className, ...$arg)
    {
        // new一个类,并且传参,需要返回
        return new $className(...$arg);
    }
}

// 通工厂类来创建实例、对象
Factory::create(Test1::class, 100);
Factory::create(Test2::class, 100, 50);
Factory::create(Test3::class, 100, 50, 1);
image.png                                            

依赖注入:

实例

<?php

namespace _1205;

// 依赖注入:解决对象调用之间的耦合
// 工作类
class Person
{
    // 创建一个属性来保存外部的依赖对象
    private $car = null;
    // 在构造方法中将依赖的外部对象全部实现实例化
    // 将注入点放到构造方法中
    public function __construct()
    {
        // 创建Car对象
        $this->car = new Car();
        // 依赖注入的目的,就是将类方法中new干掉
    }
    // 调用外部对象,执行一个动作
    public function work()
    {
        // 调用外部所依赖的对象,
        // 因为在构造方法中已经实现了依赖对象实例化,所以使用$this
        return $this->car->drive();
    }
}
// 依赖的外部对象
class Car
{
    public function drive()
    {
        return '开车';
    }
}
// 依赖类注入到工作类进行工作
// 实例化工作类
$Person = new Person();
echo $Person->work();
echo '<hr>';

// *******************************************
// 依赖注入:解决对象调用之间的耦合
// 工作类
class Person1
{
    // 创建一个属性来保存外部的依赖对象
    private $car = null;
    // 在构造方法中将依赖的外部对象全部实现实例化
    // 将注入点放到构造方法中
    public function __construct(Car1 $car)
    {
        // 创建Car对象
        $this->car = $car;
        // 依赖注入的目的,就是将类方法中new干掉
    }
    // 调用外部对象,执行一个动作
    public function work()
    {
        // 调用外部所依赖的对象,
        // 因为在构造方法中已经实现了依赖对象实例化,所以使用$this
        return $this->car->drive();
    }
}
// 依赖的外部对象
class Car1
{
    public function drive()
    {
        return '开车';
    }
}
// 依赖类注入到工作类进行工作
// 实例化Car1
$car = new Car1();
// 遇到一个问题:在工作类构造方法定义的类型变量必须一致不然会找不到实例
$person = new Person1($car);
echo $person->work();
echo '<hr>';

 image.png                    

容器:

容器类

<?php
// 容器类

namespace lessno;

// 引入闭包别名
use Closure;

class Container
{

    // 创建数组,保存类的实例化对象,也叫类实例容器
    protected $instance = [];
    /**
     *将类实例化的过程绑定到容器中
     * @param [type] $alias 当前类的别名
     * @param Closure $closure  执行过程
     * @return void
     */

    public function bind($alias, Closure $process)
    {
        /**
         * 帮获取类的实例化保存到数组中
         * [$alias]数组的健名
         * = $process数组的值
         */

        $this->instance[$alias] = $process;
    }
    // 取出保存在容器中的实例化过程的闭包,并执行它
    // 参数:实例化的那个类
    public function make($alias)
    {
        // 执行
        return $this->instance[$alias]();
    }
}

调用类

<?php

namespace lessno;

require 'Protuct.php';

require 'Maker.php';

require 'Container.php';

// 传统方式使用
class Clinet2
{
    // 输出
    // 参数1:Protuct类的实例
    // 参数2:Maker类的实例对象
    public function show(Protuct $protuct, Maker $maker)
    {
        // 将制造商注入到商品类中
        return $protuct->get($maker);
    }
}
// 调用
// 将类实例绑定到容器中并实例化返回
$container = new Container();
/**
 * 执行绑定
 * 参数1:类的别名,自定义,为了阅读,建议使用类名
 */
$container->bind('protuct', function () {
    return new Protuct();
});
$container->bind('maker', function () {
    return new Maker();
});
/**
 * 创建实例并返回
 * 参数1:绑定的别名
 * 参数2:
 */
$protuct = $container->make('protuct');
$maker = $container->make('maker');
// 创建类的实例并返回

$obj = new Clinet2();
echo $obj->show($protuct, $maker);



image.png

面向接口:

调用类

<?php

// 旅行类,使用传统方式

namespace base;


// 设置引用的类的别名
use base\inc2\Car;
use base\inc2\Plane;
use base\inc2\Train;
use base\inc2\iVehicle;

require __DIR__ . '/autoload.php';



class Travel3
{

    // 交通工具
    private $vehicle;
    // 构造方法,传入接口
    public function __construct(iVehicle $vehicle)
    {
        $this->vehicle = $vehicle;
    }
    // 调用外部依赖对象
    public function travelModel()
    {
        // 调用对象
        return $this->vehicle->drive() . ':3去旅行';
    }
}
// 客户端调用
echo (new Travel3(new Car()))->travelModel() . '<br>';
echo (new Travel3(new Plane()))->travelModel() . '<br>';
echo (new Travel3(new Train()))->travelModel() . '<br>';



image.png









                       

                                     
2. 代码中的注释文字, 不得少于代码量的四分之一。


3. 手写课堂笔记:1205.md
image.png



总结:

单列模式:构造方法私有化,添加两个静态成员来保存当前类的实例和实现该类实例化的方法。通过类名调用静态方法,实现类的唯一实例。

工厂模式:用于批量创建类的实例或对象,创建一个类,添加一个静态方法,参数1是类的名字,参数2是构造方法的参数,在方法new 参数1传参参数2,并且返回。

依赖注入:创建一个工作类,类成员有构造方法,在外部实例化依赖类,传参工作类构造方法实现依赖注入。解决对象调用之间的耦合。

容器:通过一个类来代理生成对象实例,并且执行返回,统一了实例化  

使用面向接口。功能好扩展,使代码更灵活。









声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议