博客列表 >029-12月05日-PHP第19节-单例、工厂模式、依赖注入、面向接口编程等

029-12月05日-PHP第19节-单例、工厂模式、依赖注入、面向接口编程等

冇忉丼
冇忉丼原创
2019年12月12日 00:31:30982浏览

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

单例模式(以pdo操作举例)

  1. <?php
  2. //单例模式
  3. //声明命名空间
  4. namespace _1210;
  5. class Single
  6. {
  7. //构造方法私有后,使外部不能实例化类
  8. private function __construct()
  9. {
  10. }
  11. //无法使用clone方法
  12. private function __clone()
  13. {
  14. // TODO: Implement __clone() method.
  15. }
  16. //类的实例,先赋初值
  17. public static $instance = null;
  18. public static function getInstance()
  19. {
  20. //判断当前类是否已经实例化了,没有就实例化
  21. if(is_null(self::$instance)){
  22. self::$instance = new self();
  23. }
  24. //已经实例化就返回它
  25. return self::$instance;
  26. }
  27. }
  28. $obj1 = Single::getInstance();
  29. $obj2 = Single::getInstance();
  30. var_dump($obj1 === $obj2);
  31. //创建的两个对象一样--单个实例--单例模式
  32. echo '<hr/>';
  33. //应用场景,以数据库连接举例
  34. class Db{
  35. private function __construct(...$connectParams)
  36. {
  37. $dsn = $connectParams[0];
  38. $username = $connectParams[1];
  39. $password = $connectParams[2];
  40. self::$pdo = new \PDO($dsn,$username,$password);
  41. }
  42. public static $pdo = null;
  43. public static function getInstance(...$connectParams)
  44. {
  45. //判断是否实例化了,empty?
  46. if(is_null(self::$pdo)){
  47. //与上面不同的是,这里是构造函数,不用返回self::$instance
  48. new self(...$connectParams);
  49. }
  50. return self::$pdo;
  51. }
  52. }
  53. echo '<br/>';
  54. $connectParams = ['mysql:host=localhost;dbname=anguoguo','root','root'];
  55. $pdo = Db::getInstance(...$connectParams);
  56. print_r($pdo->query('SELECT * FROM `movies`')->fetchAll());

工厂模式

  1. <?php
  2. //工厂模式--流水线生产类的实例
  3. namespace _1210;
  4. //声明工厂类,里面有生产方法,用的是静态方法--new一个实例
  5. class Factory{
  6. public static function create($className,...$params){
  7. return new $className(...$params);
  8. }
  9. }
  10. //声明商品类,有各自的方法
  11. class Goods1{
  12. public function __construct($para1)
  13. {
  14. echo '商品1创建成功,参数为: ' . $para1;
  15. }
  16. }
  17. class Goods2{
  18. public function __construct($para1,$para2)
  19. {
  20. echo '商品2创建成功,参数为: ' . implode(',',[$para1,$para2]);
  21. }
  22. }
  23. class Goods3{
  24. public function __construct($para1,$para2,$para3)
  25. {
  26. echo '商品3创建成功,参数为: ' . implode(',',[$para1,$para2,$para3]);
  27. //implode:数组转为字符串,以,为分隔依据,相对的是explode字符串转为数组,也以第一个参数为划分依据
  28. }
  29. }
  30. //静态方法调用方式,类作为参数时的写法xx::class
  31. Factory::create(Goods1::class,'甲');
  32. echo '<hr/>';
  33. Factory::create(Goods2::class,'甲','乙');
  34. echo '<hr/>';
  35. Factory::create(Goods3::class,'甲','乙','丙');

依赖注入(DI)

  1. <?php
  2. namespace _1210;
  3. //依赖注入:Dependency Injection解决对象调用之间的耦合
  4. class Someone{
  5. private $football = null;//这个类依赖的外部类的对象
  6. public function __construct()
  7. {
  8. $this->football = new Football();//此处将外部对象实例化,此处为外部对象注入点
  9. }
  10. public function relax(){
  11. return $this->football->play();//外部对象执行一个操作
  12. }
  13. }
  14. //依赖的外部类,Football
  15. class Football{
  16. public function play(){
  17. return '休息时踢足球';
  18. }
  19. }
  20. $someone = new Someone();
  21. echo $someone->relax();
  22. echo '<hr/>';
  23. /***************************************************/
  24. //也可以在外部$football = new Football(),前面构造函数处就不用new Football(),直接$football

容器类(将实例与方法放进容器,再取出生成实例)

产品:

  1. <?php
  2. namespace _1210;
  3. class Product
  4. {
  5. public function get(Maker $maker){
  6. return '这辆小钢炮是由:<span style="color:lightblue;font-weight: bolder"> ' .
  7. $maker->get() . '</span>生产';
  8. }
  9. }

生产商:

  1. <?php
  2. namespace _1210;
  3. class Maker{
  4. public function get(){
  5. return '福特';
  6. }
  7. }//生产商

容器:

  1. <?php
  2. namespace _1210;
  3. use Closure;//要用闭包
  4. class Container{
  5. protected $instance = [];//instance例子,即表示实例数组(容器)
  6. //类实例,实例方法绑定到容器中(数组)
  7. public function bind($alias,Closure $process){
  8. $this->instance[$alias] = $process;
  9. }
  10. //从容器中取出实例化过程的闭包,执行它
  11. public function make($alias){
  12. return $this->instance[$alias]();//即$process(),,()代表执行
  13. }
  14. }

容器使用:

  1. <?php
  2. namespace _1210;
  3. require 'Product.php';
  4. require 'Maker.php';//引入外部两个文件,为什么不use类呢
  5. require 'Container.php';//引入了容器类
  6. class Client2{
  7. public function show(Product $product,Maker $maker){
  8. //之前实例化的过程交给容器make,两个参数需要在这里传入吗,与类中参数相关
  9. return $product->get($maker);
  10. }
  11. }
  12. $container = new Container();
  13. $container->bind('product',function (){return new Product();});
  14. $container->bind('maker',function (){return new Maker();});
  15. $product = $container->make('product');
  16. $maker = $container->make('maker');
  17. //以上按照Container类中的流程实例化,绑定,取出执行
  18. echo (new Client2())->show($product,$maker);//称为客户端调用,同时把类实例化,这里是和实例化后的参数相关

面向接口编程

接口(给类定个规范):

  1. <?php
  2. //与inc1比多了接口
  3. namespace base\inc2;
  4. // 休闲方式的接口
  5. interface iBall
  6. {
  7. public function play();//抽象的
  8. }

休闲类(三个,生效自接口)

  1. <?php
  2. //01.Baseball类
  3. namespace base\inc2;
  4. class Baseball implements iBall {
  5. public function play(){
  6. return '打棒球';
  7. }
  8. }
  9. //02.Basketball类
  10. class Basketball implements iBall{
  11. public function play(){
  12. return '玩篮球';
  13. }
  14. }
  15. //03.Football类
  16. class Football implements iBall {
  17. public function play(){
  18. return '玩足球';
  19. }
  20. }

自动加载函数(方便引入多个文件)

  1. <?php
  2. spl_autoload_register(function ($className){//spl_autoload_register函数的参数是一个回调函数,调用该函数会将注册的加载函数放入autoload函数队列中
  3. $path = str_replace('\\','/',$className);
  4. require dirname(__DIR__) . DIRECTORY_SEPARATOR . $path . '.php';
  5. });//自动加载函数,自动加载当前同目录下的$path.php

用法:

  1. <?php
  2. //说明面向接口编程
  3. namespace base;
  4. use base\inc2\Baseball;
  5. use base\inc2\Basketball;
  6. use base\inc2\Football;
  7. use base\inc2\iBall;
  8. //在实例化以上类时,IDE会自动use
  9. require __DIR__ . '/autoload.php';//自动加载,不用require一堆文件了
  10. class Relax3{
  11. //球类
  12. private $ball;
  13. //构造方法
  14. public function __construct(iBall $ball)
  15. {
  16. $this->ball = $ball;
  17. }
  18. //调用外部一个依赖对象
  19. public function relaxModel(){
  20. return $this->ball->play() . ' : 通过接口去放松';
  21. }
  22. }
  23. //客户端调用
  24. $football =new Football();
  25. echo (new Relax3($football))->relaxModel(), '<br/>';
  26. echo (new Relax3(new Baseball()))->relaxModel(), '<br/>';//直接在调用参数的时候实例化类
  27. echo (new Relax3(new Basketball()))->relaxModel(), '<br/>';

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

朱老师,说明一下用作业本书写舒服一点,肯定有装订的。

总结

单例模式:实例就一个,常见于使用PDO建立数据模型
工厂模式:生产N个实例
依赖注入(DI):内部调用外部实例,就不要在内部实例化了,会加重类间耦合,最好在外部实例化,然后将实例作为参数传到调用类的构造方法里
容器:实例和实例化方法都放进去,要用时再拿出来
面向接口:接口是规范类的,使用抽象方法

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