Blogger Information
Blog 34
fans 0
comment 0
visits 21835
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
12月5日_设计模式、单例、工厂、服务容器、面向接口编程 - 九期线上班
只猫
Original
716 people have browsed it

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

单例模式 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>';


手写:

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

Correcting teacher:天蓬老师天蓬老师

Correction status:qualified

Teacher's comments:谢谢鼓励, 设计模式是比较难学, 所以也比较难教 , 主要是原因是案例不容易写, 写复杂了一不小心写成了完整项目, 写简单了又担心会有地方说不清楚, 感谢大家的理解 , 以后会制作出更多精彩的课程
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!