12月5日作业
1. 将课堂代码全部上机操作至少一遍以上
2. 代码中的注释文字, 不得少于代码量的四分之一
demo1
<?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{
//1.构造方法私有化
private function __construct()
{
}
//目前只能在类的内部将类实例化,这样类中访问只能用静态成员
// 当前类的实例
public static $instance=null; //可以不赋值,默认也是null
//实例化当前类的方法,类中也不能实例化调用,也要申明为一个静态方法
public static function getInstance(){
//实例化当前类,并返回实例/对象
//判断当前类是否已经被实例化过了,如果没有的化就实例化,如果已创建就返回他
if(is_null(self::$instance)){
//判断当前类实例是否是空
// 没有就创建类实例
self::$instance=new self(); //new产生的实例保存在当前静态类成员中
}
return self::$instance;
}
private function __clone()
{
// 禁用克隆魔术方法
// 设置魔术方法__clone为私有方法,内容为空
}
}
//思路:把外面实例化的操作功能禁用掉,禁用new新实例
//new Demo1();
//创建一个实例
$obj1 = Demo1::getInstance();
//再创建一个实例用于比较;
$obj2 = Demo1::getInstance();
var_dump($obj1===$obj2);
echo '<br>';
var_dump($obj1,$obj2);
//单例模式的应用场景
class Db{
//1.构造方法私有化
private function __construct(...$connectParams)
{
$dsn=$connectParams[0];
$username=$connectParams[1];
$password=$connectParams[2];
self::$pdo = new PDO($dsn,$username,$password);
}
//如果前面不加use PDO 这里要写成 \PDO() 在根目录全局下
//目前只能在类的内部将类实例化,这样类中访问只能用静态成员
// 当前类的实例
public static $pdo=null; //可以不赋值,默认也是null
//实例化当前类的方法,类中也不能实例化调用,也要申明为一个静态方法
public static function getInstance(...$connectParams)
{
//实例化当前类,并返回实例/对象
//判断当前类是否已经被实例化过了,如果没有的化就实例化,如果已创建就返回他
if(is_null(self::$pdo)){
//判断当前类实例是否是空
// 没有就创建类实例
//构造函数不需要返回,因为在__construct中self::$pdo = new PDO($dsn,$username,$password);已经初始化了
new self(...$connectParams);
//构造函数没有返回值,这里无需写成self::$pdo=new self(...$connectParams)赋值,将new产生的实例保存在当前静态类成员中的格式
}
return self::$pdo;
}
private function __clone()
{
// 禁用克隆魔术方法
// 设置魔术方法__clone为私有方法,内容为空
}
}
echo '<hr>';
$connectParams=['mysql:host=localhost;dbname=youya','root','root'];
//当前DB类实例化
$pdo =Db::getInstance(...$connectParams);
print_r($pdo->query('SELECT * FROM `user`')->fetchAll());
// 为了演示这里没用预处理
demo2
<?php
namespace _1205;
//工厂模式:批量new类生产,用于批量创建类的实例/对象
class Demo2
{
}
//file1.php
$obj1 = new Demo2();
//file2.php
$obj2 = new Demo2();
//file3.php
$obj3 = new Demo2();
/************************************************************/
//创建一个批量生成器
class Test1
{
public function __construct($arg1)
{
echo '对象创建成功,参数是:'.$arg1;
}
}
class Test2
{
public function __construct($arg1,$arg2)
{
echo '对象创建成功,参数是:'.implode(',',[$arg1,$arg2]);
//数组切割implode拆成字符串
}
}
class Test3
{
public function __construct($arg1,$arg2,$arg3)
{
echo '对象创建成功,参数是:'.implode(',',[$arg1,$arg2,$arg3]);
//数组切割implode拆成字符串
}
}
//把上面三个类Test1,Test2,Test3,都实例化
//原始的笨办法 new Test1();new Test2();new Test3();
//现在优化的方法就是用工厂类
class Factory
{
//尽可能不要实例化,用类来访问,写成静态方法
// creat(类名称,构造方法的参数)
public static function creat($className,...$argments)
{
//里面专业new类,最后return出来给调用者
return new $className(...$argments);
}
}
echo Test1::class; //Test1::class返回来的类名是带有命名空间的完成的类名
//用工厂类来创建类实例
Factory::creat(Test1::class,100);
//☆☆☆☆☆☆☆☆注意,类是有命名空间的,要写上命名空间,不要忽略了,写成_1205\Test1,或者Test1::class
echo '<hr>';
Factory::creat(Test2::class,100,200);
echo '<hr>';
Factory::creat(Test3::class,100,200,300);
demo3 依赖注入的知识复习
<?php
namespace _1205;
//依赖注入:解决对象调用之间的耦合问题
//依赖注入需要两个类:
//1.工作类 :真正干活的
class Person
{
//这是一个工作类,先把要依赖的外部对象创建成属性
private $car=null;
//构造方法中把依赖的外部对象全部实例化
//就是把注入点放在构造方法中,在new的过程中直接完成注入
public function __construct()
// 依赖注入的目标就是将类方法中的new干掉
{
$this->car=new Car();
}
// 外部对象执行一个动作
public function work()
{
return $this->car->drive();
}
}
//2.依赖的外部类
class Car
{
// 这个Car类就是Person类所依赖的外部对象
public function drive()
{
return '开车去上班';
}
}
//客户端访问 实例化工作类(真正干活的)
$person=new Person();
//然后直接访问工作类的一个方法
echo $person->work();
echo '<hr>';
//以上为传统模式,但耦合度太高,类中出现类new 实例化对象方法
/***************************************************************/
//那么在那里实例化呢?把它放在客户端
class Person1
{
//这是一个工作类,先把要依赖的外部对象创建成属性
private $car=null;
//构造方法中把依赖的外部对象全部实例化
//就是把注入点放在构造方法中,在new的过程中直接完成注入
public function __construct(Car $car)
// 这里先写一个类型申明,然后创建一个变量叫$car,这样就实现了通过外部对象注入到当前类中
// 依赖注入的目标就是将类方法中的new干掉
{
$this->car=$car;
}
// 外部对象执行一个动作
public function work()
{
return $this->car->drive();
}
}
//2.依赖的外部类
class Car1
{
// 这个Car类就是Person类所依赖的外部对象
public function drive()
{
return '开车去上班';
}
}
//客户端访问 实例化工作类(真正干活的)
//那么在那里实例化呢?把它放在客户端:$car=new Car();,然后注入到构造方法的参数中$person=new Person1($car)
$car=new Car();
$person=new Person1($car);
//然后直接访问工作类的一个方法
echo $person->work();
echo '<hr>';
demo4容器的知识复习
<?php
//容器类
namespace _1205;
//引入闭包别名
use Closure; //类的new创建过程代码是个闭包函数,先use引入
class Container
{
//类实例容器
protected $instance=[];
// 1.将类实例化的过程绑定到容器中
public function bind($alias,Closure $process)
//绑定的时候需要参数?哪些参数--实例对象名,绑定过程的闭包函数
{
$this->instance[$alias]=$process;
// $product=new Product(); ↑对应关系
}
// 2.取出保存在容器中的实例化过程的闭包,并执行它
public function make($alias)
{
return $this->instance[$alias]();
// 用户代理call_user_func_array是异步调用的过程,由系统决定何时运行,不会导致堵塞
}
}
<?php
namespace _1205;
//先不用容器.用传统方式
//先创建一个客户端的类
use http\Client;
require 'Product.php';
require 'Maker.php';
require 'Container.php';
//把产品类和制造商类导入
class Client2
{
// 输出商品与制造商
public function show(Product $product,Maker $maker)
{
// //1.创建一个产品的实例
// $product=new Product();
// //2.创建一个制造商的实例
// $maker=new Maker();
// 用了容器,传统方法的1.2.步骤就不用了
//3.把制造商注入到产品类中
return $product->get($maker);
}
}
//客户端调用
//将类实例绑定到容器中并实例化且返回
$container = new Container();
//将实例化代码绑定到容器实例中
$container->bind('product',function(){return new Product();});
$container->bind('maker',function(){return new Maker();});
//这里bind('product')别名无所谓,写'abc'也可以,只要对应起来就可以,function()不用参数{return new 类}
//创建实例并返回
$product=$container->make('product');
// 这里make要传参数,你调用谁就传谁,实例化的别名
$maker=$container->make('maker');
echo (new Client2())->show($product,$maker);
//依赖注入
demo5
<?php
//旅行,使用最原始的方式
namespace base;
//设置引用的外部别名
use base\inc2\Car;
use base\inc2\Ship;
use base\inc2\Train;
use base\inc2\Plane;
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().'======去旅行';
}
}
//客户端调用
$car=new Car();
echo (new Travel3($car))->travelModel().'<br>';
//这里需要传参,传什么参数,这里需要的是一个对象了public function __construct(iVehicle $vehicle)
echo (new Travel3(new Train()))->travelModel().'<br>';
echo (new Travel3(new Plane()))->travelModel().'<br>';
echo (new Travel3(new Ship()))->travelModel().'<br>';
3. 手写课堂笔记:1205.md
.
课堂小结:
1.单例模式
思路:把外面实例化的操作功能禁用掉,禁用new新实例,把构造方法__congstruct改为private
目前只能在类的内部将类实例化,这样类中访问只能用静态成员,成员属性和方法都static静态化
判断当前类是否已经被实例化过了,如果没有的化就实例化,如果已创建就返回他
2.工厂模式
批量new类生产,用于批量创建类的实例/对象
尽可能不要实例化,用类来访问,写成静态方法
public static function creat($className,...$argments)
{
//里面专业new类,最后return出来给调用者
return new $className(...$argments);
}
3.依赖注入
目标:就是将类方法中的new干掉,解决对象调用之间的耦合问题。除了单例模式,其他类中尽量不要出现new xxx()实例化类;
那么不要new在那里实例化呢?——把它放在客户端
拿到对象后,把他注入到构造方法中作为参数*
依赖注入需要两个类:
(1)工作类 :真正干活的
构造方法中把依赖的外部对象全部实例化,方法很简单,就是把注入点放在构造方法中作为参数
(2)依赖的外部类
4.容器复习
容器里有个数组
例如$instance[对象]=类的new创建过程代码
关键:
(1)类实例容器$instance=[];
(1)放进去:将类实例化的过程绑定到容器中 bind()//绑定的时候需要参数?哪些参数—实例对象名,绑定过程的闭包函数
(2)取出来用:取出保存在容器中的实例化过程的闭包,并执行它。
make()对应类的new创建过程代码
结合用户代理来用call_user_func_arry()
面向接口编程
接口命名规划用小写开头 如iVehicle
implements实现接口类
小技巧:按alt键选择可以多点编辑
//构造方法
public function __construct(iVehicle $vehicle)
{
$this->vehicle=$vehicle;
}