博客列表 >12月5日_设计模式、单例、工厂、服务容器、面向接口编程 - 九期线上班

12月5日_设计模式、单例、工厂、服务容器、面向接口编程 - 九期线上班

只猫
只猫原创
2019年12月06日 19:23:02717浏览

设计模式 单例、工厂、容器、面向接口

单例模式 demo1
  1. <?php
  2. namespace _1205;
  3. //设计模式 - 单例模式
  4. //单例:类的唯一实例
  5. //这个类只允许new一个对象。重复new还是那同一个对象
  6. //举例Temp
  7. class Temp
  8. {
  9. }
  10. $obj1 = new Temp(); //object(_1205\Temp)#1 (0) { }
  11. $obj2 = new Temp(); //object(_1205\Temp)#2 (0) { }
  12. var_dump($obj1, $obj2);
  13. echo '<br>';
  14. var_dump($obj1 === $obj2); //bool(false)
  15. echo '<hr>';
  16. //比如单例模式用于数据库连接 (数据库连接数量有上限)
  17. //单例Demo1
  18. class Demo1
  19. {
  20. //1.new类的时候会自动调用类的构造方法
  21. //那么将构造方法私有,这个类在外部将无法访问
  22. private function __construct(){
  23. //私有的构造方法 禁止外部new
  24. }
  25. //这个时候这个类一个实例都没有
  26. //类中成员只能用类本身来访问 静态成员$instance
  27. public static $instance = null;
  28. //2.在类的内部写一个创建自己的实例的方法
  29. //全球限量唯一发售
  30. public static function getInstance(){
  31. //先判断自己是否已经实例化过
  32. if(is_null(self::$instance)){
  33. self::$instance = new self();
  34. }
  35. return self::$instance;
  36. //已创建过,返回自己的唯一对象
  37. }
  38. //3.禁止克隆这个类
  39. private function __clone(){
  40. //__clone方法在类被克隆时自动调用,用于重写克隆体的成员。
  41. //把这个禁止就像禁用了构造方法无法new一样无法被克隆。
  42. }
  43. }
  44. //调用
  45. $obj1 = Demo1::getInstance(); //object(_1205\Demo1)#3 (0) { }
  46. $obj2 = Demo1::getInstance(); //object(_1205\Demo1)#3 (0) { }
  47. var_dump($obj1,$obj2);
  48. echo '<br>';
  49. var_dump($obj1===$obj2); //bool(true)
案例:数据库连接
  1. <?php
  2. namespace _1205;
  3. use PDO;
  4. //单例模式连接数据库
  5. class Db
  6. {
  7. private function __construct(...$connectParams){
  8. $dsn = $connectParams[0];
  9. $username = $connectParams[1];
  10. $password = $connectParams[2];
  11. self::$pdo = new PDO($dsn,$username,$password);
  12. }
  13. public static $pdo = null;
  14. //2.方法接收参数
  15. public static function getInstance(...$connectParams){
  16. //先判断自己是否已经实例化过
  17. if(is_null(self::$pdo)){
  18. //构造函数不需要返回值
  19. new self(...$connectParams);
  20. }
  21. return self::$pdo;
  22. //已创建过,返回自己的唯一对象
  23. }
  24. private function __clone(){
  25. }
  26. }
  27. //设置参数
  28. $connectParams = [
  29. 'mysql:host=localhost;dbname=php_2019',
  30. 'root',
  31. 12341234
  32. ];
  33. //获取对象
  34. $pdo = Db::getInstance(...$connectParams);
  35. //打印数据
  36. echo '<pre>';
  37. print_r($pdo->query('SELECT * FROM `user`')->fetchAll());
  38. echo '</pre>';
demo2 工厂模式
  1. <?php
  2. namespace _1205;
  3. //工厂模式
  4. class Demo2
  5. {
  6. //...
  7. }
  8. //不同的file都要创建Demo2的实例
  9. $obj = new Demo2();
  10. $obj = new Demo2();
  11. /******************************************/
  12. class Test1
  13. {
  14. public function __construct($arg1)
  15. {
  16. echo '对象创建成功,参数为'.$arg1.'<br>';
  17. }
  18. }
  19. class Test2
  20. {
  21. public function __construct($arg1,$arg2)
  22. {
  23. echo '对象创建成功,参数为'.implode(',', [$arg1,$arg2]).'<br>';
  24. }
  25. }
  26. class Test3
  27. {
  28. public function __construct($arg1,$arg2,$arg3)
  29. {
  30. echo '对象创建成功,参数为'.implode(',', [$arg1,$arg2,$arg3]).'<br>';
  31. }
  32. }
  33. //工厂 来生产类的实例
  34. class Factory
  35. {
  36. public static function create($className,...$args){
  37. return new $className(...$args);
  38. }
  39. }
  40. //生产
  41. //Test1::class 等于 _1205\Test1
  42. Factory::create(Test1::class,100);
  43. Factory::create(Test2::class,100,200);
  44. Factory::create(Test3::class,100,200,300);

demo3 依赖注入
  1. <?php
  2. namespace _1205;
  3. //依赖注入
  4. //一般情况下
  5. //工作类
  6. class Person1
  7. {
  8. //人依赖汽车去上班
  9. private $car = null;
  10. //构造方法中将依赖的外部对象全部实例化
  11. public function __construct(){
  12. //类方法中出现了new 代表耦合很高
  13. $this->car = new Car1();
  14. }
  15. public function toWork(){
  16. return $this->car->drive();
  17. }
  18. }
  19. //依赖类
  20. class Car1
  21. {
  22. public function drive(){
  23. return '开车去上班';
  24. }
  25. }
  26. //客户端调用
  27. //实例化
  28. $p1 = new Person1();
  29. echo $p1->toWork();
  30. echo '<hr>';
  31. /*************************************/
  32. //将依赖注入 解决在类中使用new的情况
  33. class Person2
  34. {
  35. //人依赖汽车去上班
  36. private $car = null;
  37. //构造方法中将依赖的外部对象全部实例化
  38. //把$car2传入到构造方法
  39. public function __construct(Car2 $car2){
  40. //消除了new 用外部创建的$car2代替
  41. $this->car = $car2;
  42. }
  43. public function toWork(){
  44. return $this->car->drive();
  45. }
  46. }
  47. //依赖类
  48. class Car2
  49. {
  50. public function drive(){
  51. return '开车去上班';
  52. }
  53. }
  54. //客户端调用
  55. //Car类在外部实例化 再将得到的$car注入到Person的构造方法中
  56. $car2 = new Car2();
  57. //这里记得new时候给类传参,因为构造方法需要参数
  58. $p2 = new Person2($car2);
  59. echo $p2->toWork();
  60. echo '<hr>';
lesson1 容器

1.Maker

  1. <?php
  2. namespace _1205;
  3. //制造商类
  4. class Maker
  5. {
  6. public function get(){
  7. return '华为';
  8. }
  9. }

2.Product

  1. <?php
  2. namespace _1205;
  3. //产品类
  4. class Product
  5. {
  6. //$maker Maker类的一个实例
  7. public function get(Maker $maker){
  8. return '该手机是由:<span style="color:red;font-weight:bolder">'. $maker->get() .'</span>生产的';
  9. }
  10. }

3.demo1 不使用容器的类调用

  1. <?php
  2. namespace _1205;
  3. //客户端调用
  4. require 'Product.php';
  5. require 'Maker.php';
  6. //不使用容器 对两个类进行调用
  7. class Client1
  8. {
  9. public function show(){
  10. //创建产品实例
  11. $product = new Product();
  12. //制造商实例
  13. $maker = new Maker();
  14. //制造商注入到产品类里
  15. return $product->get($maker);
  16. }
  17. }
  18. //客户端调用
  19. //节省了一个对象
  20. echo (new Client1())->show();

4.Container 写个容器

  1. <?php
  2. namespace _1205;
  3. //引入闭包别名
  4. use Closure;
  5. class Container
  6. {
  7. //容器数组
  8. protected $instance = [];
  9. //类实例化过程绑定到容器中
  10. public function bind($alias,Closure $process){
  11. //类的实例化代码绑定到类名
  12. $this->instance[$alias] = $process;
  13. }
  14. //取出保存在容器中的类实例化闭包 并执行它
  15. public function make($alias){
  16. //return $this->instance[$alias]();
  17. return call_user_func_array($this->instance[$alias] , []);
  18. }
  19. }

5.demo 使用容器的类调用

  1. <?php
  2. namespace _1205;
  3. //客户端调用
  4. require 'Product.php';
  5. require 'Maker.php';
  6. require 'Container.php';
  7. //使用容器 对两个类进行调用
  8. class Client2
  9. {
  10. public function show(Product $product, Maker $maker){
  11. //制造商注入到产品类里
  12. return $product->get($maker);
  13. }
  14. }
  15. //实例化Container
  16. $container = new Container();
  17. //开始绑定
  18. //将产品类与实例化代码绑定到容器中
  19. //这里别名随便取
  20. $container->bind('product',function(){return new Product();});
  21. //将制造商类与实例化代码绑定到容器中
  22. $container->bind('maker',function(){return new Maker();});
  23. //创建产品实例并返回给一个变量
  24. //这里make传入的类名就是之前起的别名
  25. $product = $container->make('product');
  26. //创建制造商实例并返回给一个变量
  27. $maker = $container->make('maker');
  28. //客户端调用
  29. echo (new Client2())->show($product,$maker);

结果:

base 面向接口编程

autoload.php

  1. <?php
  2. spl_autoload_register(function($className){
  3. $path = str_replace('\\', '/', $className);
  4. require dirname(__DIR__).DIRECTORY_SEPARATOR.$path.'.php';
  5. });

inc1
Car.php

  1. <?php
  2. namespace base\inc1;
  3. class Car
  4. {
  5. public function drive(){
  6. return '开汽车';
  7. }
  8. }

Train.php

  1. <?php
  2. namespace base\inc1;
  3. class Train
  4. {
  5. public function drive(){
  6. return '坐火车';
  7. }
  8. }

Plane.php

  1. <?php
  2. namespace base\inc1;
  3. class Plane
  4. {
  5. public function drive(){
  6. return '坐飞机';
  7. }
  8. }

Travel1

  1. <?php
  2. namespace base;
  3. use base\inc1\Car;
  4. use base\inc1\Train;
  5. use base\inc1\Plane;
  6. require __DIR__.'/autoload.php';
  7. //最原始
  8. class Travel1
  9. {
  10. private $vehicle;
  11. //构造方法
  12. public function __construct($vehicle){
  13. //传入不同参数 实例化不同类
  14. //严重依赖
  15. switch (strtolower($vehicle)){
  16. case 'car':
  17. $this->vehicle = new Car();
  18. break;
  19. case 'train':
  20. $this->vehicle = new Train();
  21. break;
  22. case 'plane':
  23. $this->vehicle = new Plane();
  24. }
  25. }
  26. public function travelModel(){
  27. return $this->vehicle->drive().'去旅行';
  28. }
  29. }
  30. //客户端调用
  31. echo (new Travel1('car'))->travelModel().'<br>';
  32. echo (new Travel1('plane'))->travelModel().'<br>';
  33. echo (new Travel1('train'))->travelModel().'<br>';

Travel2

  1. <?php
  2. namespace base;
  3. use base\inc1\Car;
  4. use base\inc1\Train;
  5. use base\inc1\Plane;
  6. require __DIR__.'/autoload.php';
  7. //用工厂
  8. class Factory
  9. {
  10. protected static $instance = null;
  11. public static function getInstance($vehicle){
  12. //传入不同参数 实例化不同类
  13. switch (strtolower($vehicle)){
  14. case 'car':
  15. static::$instance = new Car();
  16. break;
  17. case 'train':
  18. static::$instance = new Train();
  19. break;
  20. case 'plane':
  21. static::$instance = new Plane();
  22. }
  23. //返回
  24. return self::$instance;
  25. }
  26. }
  27. class Travel2
  28. {
  29. private $vehicle;
  30. //构造方法
  31. public function __construct($vehicle){
  32. //一句代码从工厂获取实例对象
  33. //依赖一个工厂。。
  34. $this->vehicle = Factory::getInstance($vehicle);
  35. }
  36. public function travelModel(){
  37. return $this->vehicle->drive().'===去旅行';
  38. }
  39. }
  40. //客户端调用
  41. echo (new Travel2('car'))->travelModel().'<br>';
  42. echo (new Travel2('plane'))->travelModel().'<br>';
  43. echo (new Travel2('train'))->travelModel().'<br>';


inc2
Car.php、Train.php、Plane.php 外添加一个 Ship.php 都实现了iVehicle接口

  1. <?php
  2. namespace base\inc2;
  3. class Ship implements iVehicle
  4. {
  5. public function drive(){
  6. return '坐轮船';
  7. }
  8. }

接口 iVehicle.php

  1. <?php
  2. namespace base\inc2;
  3. //交通工具接口
  4. interface iVehicle
  5. {
  6. public function drive();
  7. }

Travel3

  1. <?php
  2. namespace base;
  3. use base\inc2\Car;
  4. use base\inc2\Train;
  5. use base\inc2\Plane;
  6. use base\inc2\Ship;
  7. use base\inc2\iVehicle;
  8. //自动加载
  9. require __DIR__.'/autoload.php';
  10. //用接口
  11. class Travel3
  12. {
  13. private $vehicle;
  14. //构造方法 这里需要接收一个对象,就是实现了vehicle接口的对象
  15. public function __construct(iVehicle $vehicle){
  16. $this->vehicle = $vehicle;
  17. }
  18. public function travelModel(){
  19. return $this->vehicle->drive().'@@@去旅行';
  20. }
  21. }
  22. //客户端调用
  23. //这里new 的时候 传入一个对象
  24. echo (new Travel3(new Car()))->travelModel().'<br>';
  25. echo (new Travel3(new Plane()))->travelModel().'<br>';
  26. echo (new Travel3(new Train()))->travelModel().'<br>';
  27. echo (new Travel3(new Ship()))->travelModel().'<br>';


手写:

总结:类里面的方法调用相互传参的步骤还是会晕。一步一步看好像又明白了。。其实没啥难的。。。吧。。设计模式这种东西真的蛮烧脑的。很耐人寻味。老师讲课真的很认真也特别用心。作为听讲者也要好好学啊。

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