博客列表 >设计模式与服务容器-第九期PHP线上班

设计模式与服务容器-第九期PHP线上班

emagic
emagic原创
2019年12月08日 22:54:14653浏览

12月5日作业

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

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



demo1

  1. <?php
  2. namespace _1205;
  3. use PDO;
  4. //单例模式
  5. class Temp{
  6. }
  7. //创建一个实例
  8. $obj1 = new Temp();
  9. //再创建一个实例用于比较;
  10. $obj2 = new Temp();
  11. //查看对象的类型
  12. var_dump($obj1,$obj2);
  13. echo '<br>';
  14. var_dump($obj1===$obj2);
  15. //这样创建的实体其实是两个完全不同的对象
  16. echo '<hr>';
  17. //单例模式
  18. //应该场景,如数据库连接,只允许有限的连接数,不允许无限连接,一般一个对象创建一次连接就行
  19. class Demo1{
  20. //1.构造方法私有化
  21. private function __construct()
  22. {
  23. }
  24. //目前只能在类的内部将类实例化,这样类中访问只能用静态成员
  25. // 当前类的实例
  26. public static $instance=null; //可以不赋值,默认也是null
  27. //实例化当前类的方法,类中也不能实例化调用,也要申明为一个静态方法
  28. public static function getInstance(){
  29. //实例化当前类,并返回实例/对象
  30. //判断当前类是否已经被实例化过了,如果没有的化就实例化,如果已创建就返回他
  31. if(is_null(self::$instance)){
  32. //判断当前类实例是否是空
  33. // 没有就创建类实例
  34. self::$instance=new self(); //new产生的实例保存在当前静态类成员中
  35. }
  36. return self::$instance;
  37. }
  38. private function __clone()
  39. {
  40. // 禁用克隆魔术方法
  41. // 设置魔术方法__clone为私有方法,内容为空
  42. }
  43. }
  44. //思路:把外面实例化的操作功能禁用掉,禁用new新实例
  45. //new Demo1();
  46. //创建一个实例
  47. $obj1 = Demo1::getInstance();
  48. //再创建一个实例用于比较;
  49. $obj2 = Demo1::getInstance();
  50. var_dump($obj1===$obj2);
  51. echo '<br>';
  52. var_dump($obj1,$obj2);
  53. //单例模式的应用场景
  54. class Db{
  55. //1.构造方法私有化
  56. private function __construct(...$connectParams)
  57. {
  58. $dsn=$connectParams[0];
  59. $username=$connectParams[1];
  60. $password=$connectParams[2];
  61. self::$pdo = new PDO($dsn,$username,$password);
  62. }
  63. //如果前面不加use PDO 这里要写成 \PDO() 在根目录全局下
  64. //目前只能在类的内部将类实例化,这样类中访问只能用静态成员
  65. // 当前类的实例
  66. public static $pdo=null; //可以不赋值,默认也是null
  67. //实例化当前类的方法,类中也不能实例化调用,也要申明为一个静态方法
  68. public static function getInstance(...$connectParams)
  69. {
  70. //实例化当前类,并返回实例/对象
  71. //判断当前类是否已经被实例化过了,如果没有的化就实例化,如果已创建就返回他
  72. if(is_null(self::$pdo)){
  73. //判断当前类实例是否是空
  74. // 没有就创建类实例
  75. //构造函数不需要返回,因为在__construct中self::$pdo = new PDO($dsn,$username,$password);已经初始化了
  76. new self(...$connectParams);
  77. //构造函数没有返回值,这里无需写成self::$pdo=new self(...$connectParams)赋值,将new产生的实例保存在当前静态类成员中的格式
  78. }
  79. return self::$pdo;
  80. }
  81. private function __clone()
  82. {
  83. // 禁用克隆魔术方法
  84. // 设置魔术方法__clone为私有方法,内容为空
  85. }
  86. }
  87. echo '<hr>';
  88. $connectParams=['mysql:host=localhost;dbname=youya','root','root'];
  89. //当前DB类实例化
  90. $pdo =Db::getInstance(...$connectParams);
  91. print_r($pdo->query('SELECT * FROM `user`')->fetchAll());
  92. // 为了演示这里没用预处理

demo2

  1. <?php
  2. namespace _1205;
  3. //工厂模式:批量new类生产,用于批量创建类的实例/对象
  4. class Demo2
  5. {
  6. }
  7. //file1.php
  8. $obj1 = new Demo2();
  9. //file2.php
  10. $obj2 = new Demo2();
  11. //file3.php
  12. $obj3 = new Demo2();
  13. /************************************************************/
  14. //创建一个批量生成器
  15. class Test1
  16. {
  17. public function __construct($arg1)
  18. {
  19. echo '对象创建成功,参数是:'.$arg1;
  20. }
  21. }
  22. class Test2
  23. {
  24. public function __construct($arg1,$arg2)
  25. {
  26. echo '对象创建成功,参数是:'.implode(',',[$arg1,$arg2]);
  27. //数组切割implode拆成字符串
  28. }
  29. }
  30. class Test3
  31. {
  32. public function __construct($arg1,$arg2,$arg3)
  33. {
  34. echo '对象创建成功,参数是:'.implode(',',[$arg1,$arg2,$arg3]);
  35. //数组切割implode拆成字符串
  36. }
  37. }
  38. //把上面三个类Test1,Test2,Test3,都实例化
  39. //原始的笨办法 new Test1();new Test2();new Test3();
  40. //现在优化的方法就是用工厂类
  41. class Factory
  42. {
  43. //尽可能不要实例化,用类来访问,写成静态方法
  44. // creat(类名称,构造方法的参数)
  45. public static function creat($className,...$argments)
  46. {
  47. //里面专业new类,最后return出来给调用者
  48. return new $className(...$argments);
  49. }
  50. }
  51. echo Test1::class; //Test1::class返回来的类名是带有命名空间的完成的类名
  52. //用工厂类来创建类实例
  53. Factory::creat(Test1::class,100);
  54. //☆☆☆☆☆☆☆☆注意,类是有命名空间的,要写上命名空间,不要忽略了,写成_1205\Test1,或者Test1::class
  55. echo '<hr>';
  56. Factory::creat(Test2::class,100,200);
  57. echo '<hr>';
  58. Factory::creat(Test3::class,100,200,300);

demo3 依赖注入的知识复习

  1. <?php
  2. namespace _1205;
  3. //依赖注入:解决对象调用之间的耦合问题
  4. //依赖注入需要两个类:
  5. //1.工作类 :真正干活的
  6. class Person
  7. {
  8. //这是一个工作类,先把要依赖的外部对象创建成属性
  9. private $car=null;
  10. //构造方法中把依赖的外部对象全部实例化
  11. //就是把注入点放在构造方法中,在new的过程中直接完成注入
  12. public function __construct()
  13. // 依赖注入的目标就是将类方法中的new干掉
  14. {
  15. $this->car=new Car();
  16. }
  17. // 外部对象执行一个动作
  18. public function work()
  19. {
  20. return $this->car->drive();
  21. }
  22. }
  23. //2.依赖的外部类
  24. class Car
  25. {
  26. // 这个Car类就是Person类所依赖的外部对象
  27. public function drive()
  28. {
  29. return '开车去上班';
  30. }
  31. }
  32. //客户端访问 实例化工作类(真正干活的)
  33. $person=new Person();
  34. //然后直接访问工作类的一个方法
  35. echo $person->work();
  36. echo '<hr>';
  37. //以上为传统模式,但耦合度太高,类中出现类new 实例化对象方法
  38. /***************************************************************/
  39. //那么在那里实例化呢?把它放在客户端
  40. class Person1
  41. {
  42. //这是一个工作类,先把要依赖的外部对象创建成属性
  43. private $car=null;
  44. //构造方法中把依赖的外部对象全部实例化
  45. //就是把注入点放在构造方法中,在new的过程中直接完成注入
  46. public function __construct(Car $car)
  47. // 这里先写一个类型申明,然后创建一个变量叫$car,这样就实现了通过外部对象注入到当前类中
  48. // 依赖注入的目标就是将类方法中的new干掉
  49. {
  50. $this->car=$car;
  51. }
  52. // 外部对象执行一个动作
  53. public function work()
  54. {
  55. return $this->car->drive();
  56. }
  57. }
  58. //2.依赖的外部类
  59. class Car1
  60. {
  61. // 这个Car类就是Person类所依赖的外部对象
  62. public function drive()
  63. {
  64. return '开车去上班';
  65. }
  66. }
  67. //客户端访问 实例化工作类(真正干活的)
  68. //那么在那里实例化呢?把它放在客户端:$car=new Car();,然后注入到构造方法的参数中$person=new Person1($car)
  69. $car=new Car();
  70. $person=new Person1($car);
  71. //然后直接访问工作类的一个方法
  72. echo $person->work();
  73. echo '<hr>';

demo4容器的知识复习

  1. <?php
  2. //容器类
  3. namespace _1205;
  4. //引入闭包别名
  5. use Closure; //类的new创建过程代码是个闭包函数,先use引入
  6. class Container
  7. {
  8. //类实例容器
  9. protected $instance=[];
  10. // 1.将类实例化的过程绑定到容器中
  11. public function bind($alias,Closure $process)
  12. //绑定的时候需要参数?哪些参数--实例对象名,绑定过程的闭包函数
  13. {
  14. $this->instance[$alias]=$process;
  15. // $product=new Product(); ↑对应关系
  16. }
  17. // 2.取出保存在容器中的实例化过程的闭包,并执行它
  18. public function make($alias)
  19. {
  20. return $this->instance[$alias]();
  21. // 用户代理call_user_func_array是异步调用的过程,由系统决定何时运行,不会导致堵塞
  22. }
  23. }
  1. <?php
  2. namespace _1205;
  3. //先不用容器.用传统方式
  4. //先创建一个客户端的类
  5. use http\Client;
  6. require 'Product.php';
  7. require 'Maker.php';
  8. require 'Container.php';
  9. //把产品类和制造商类导入
  10. class Client2
  11. {
  12. // 输出商品与制造商
  13. public function show(Product $product,Maker $maker)
  14. {
  15. // //1.创建一个产品的实例
  16. // $product=new Product();
  17. // //2.创建一个制造商的实例
  18. // $maker=new Maker();
  19. // 用了容器,传统方法的1.2.步骤就不用了
  20. //3.把制造商注入到产品类中
  21. return $product->get($maker);
  22. }
  23. }
  24. //客户端调用
  25. //将类实例绑定到容器中并实例化且返回
  26. $container = new Container();
  27. //将实例化代码绑定到容器实例中
  28. $container->bind('product',function(){return new Product();});
  29. $container->bind('maker',function(){return new Maker();});
  30. //这里bind('product')别名无所谓,写'abc'也可以,只要对应起来就可以,function()不用参数{return new 类}
  31. //创建实例并返回
  32. $product=$container->make('product');
  33. // 这里make要传参数,你调用谁就传谁,实例化的别名
  34. $maker=$container->make('maker');
  35. echo (new Client2())->show($product,$maker);
  36. //依赖注入

demo5

  1. <?php
  2. //旅行,使用最原始的方式
  3. namespace base;
  4. //设置引用的外部别名
  5. use base\inc2\Car;
  6. use base\inc2\Ship;
  7. use base\inc2\Train;
  8. use base\inc2\Plane;
  9. use base\inc2\iVehicle; //导入接口空间
  10. require __DIR__ . '/autoload.php'; //自动加载类
  11. class Travel3
  12. {
  13. //交通工具
  14. private $vehicle;
  15. //构造方法
  16. public function __construct(iVehicle $vehicle)
  17. {
  18. $this->vehicle=$vehicle;
  19. // 实现了接口的类实例可以这样直接调用
  20. }
  21. // 调用外部依赖对象
  22. public function travelModel()
  23. {
  24. return $this->vehicle->drive().'======去旅行';
  25. }
  26. }
  27. //客户端调用
  28. $car=new Car();
  29. echo (new Travel3($car))->travelModel().'<br>';
  30. //这里需要传参,传什么参数,这里需要的是一个对象了public function __construct(iVehicle $vehicle)
  31. echo (new Travel3(new Train()))->travelModel().'<br>';
  32. echo (new Travel3(new Plane()))->travelModel().'<br>';
  33. echo (new Travel3(new Ship()))->travelModel().'<br>';

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


.

课堂小结:

1.单例模式

思路:把外面实例化的操作功能禁用掉,禁用new新实例,把构造方法__congstruct改为private
目前只能在类的内部将类实例化,这样类中访问只能用静态成员,成员属性和方法都static静态化
判断当前类是否已经被实例化过了,如果没有的化就实例化,如果已创建就返回他

2.工厂模式

批量new类生产,用于批量创建类的实例/对象
尽可能不要实例化,用类来访问,写成静态方法

  1. public static function creat($className,...$argments)
  2. {
  3. //里面专业new类,最后return出来给调用者
  4. return new $className(...$argments);
  5. }

3.依赖注入

目标:就是将类方法中的new干掉,解决对象调用之间的耦合问题。除了单例模式,其他类中尽量不要出现new xxx()实例化类;
那么不要new在那里实例化呢?——把它放在客户端 拿到对象后,把他注入到构造方法中作为参数*
依赖注入需要两个类:

(1)工作类 :真正干活的

构造方法中把依赖的外部对象全部实例化,方法很简单,就是把注入点放在构造方法中作为参数

(2)依赖的外部类

4.容器复习

容器里有个数组
例如$instance[对象]=类的new创建过程代码
关键:
(1)类实例容器$instance=[];
(1)放进去:将类实例化的过程绑定到容器中 bind()//绑定的时候需要参数?哪些参数—实例对象名,绑定过程的闭包函数
(2)取出来用:取出保存在容器中的实例化过程的闭包,并执行它。
make()对应类的new创建过程代码
结合用户代理来用call_user_func_arry()

面向接口编程

接口命名规划用小写开头 如iVehicle
implements实现接口类
小技巧:按alt键选择可以多点编辑

  1. //构造方法
  2. public function __construct(iVehicle $vehicle)
  3. {
  4. $this->vehicle=$vehicle;
  5. }
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议