单例模式
<?php
namespace _1205;
//单例模式:只允许存在一个实例对象,对类实例化得到的都是相同的一个实例,确保所有对象都访问一个实例
class Temp{
//...
}
//用同一个类创建的实例,每次创建的实例都是不同的,不是同一个实例
$obj1 = new Temp();
$obj2 = new Temp();
var_dump($obj1,$obj2);
echo '<br>';
var_dump($obj1===$obj2);
echo '<hr>';
//单例模式原理
class Demo1{
//构造方法私有化
private function __construct(){
//...
}
//因为构造方法私有化,在类外部不能实例化类了,只能在类中将类实例化
public static $instance = null;
//实例化当前类的方法
public static function getInstance(){
//实例化当前类,并返回实例化对象
//判断当前类是否已经实例化
if (is_null(self::$instance)){
self::$instance = new self();
}
return self::$instance;
}
//禁用克隆魔术方法
private function __clone(){
//...
}
}
//测试方法
$obj1 = Demo1::getInstance();
$obj2 = Demo1::getInstance();
var_dump($obj1,$obj2);
echo '<br>';
var_dump($obj1===$obj2);
echo '<hr>';
//测试结果:通过单例模式生成的实例化对象都是同一个,不管生成多少次
//单例模式应用场景:数据库连接
class Db{
//定义静态数据库连接pdo
public static $pdo = null;
//构造方法私有化
private function __construct(...$connectParams){
$dsn = $connectParams[0];
$user = $connectParams[1];
$pwd = $connectParams[2];
self::$pdo = new \PDO($dsn,$user,$pwd);
}
public static function getInstance(...$connectParams){
if (is_null(self::$pdo)){
new self(...$connectParams);
}
return self::$pdo;
}
//禁用克隆魔术方法
private function __clone(){
//...
}
}
echo '<hr>';
$connectParams = ['mysql:host=localhost;dbname=demo','root','root'];
$pdo = Db::getInstance(...$connectParams);
print_r($pdo->query('select * from `user`')->fetchAll(\PDO::FETCH_ASSOC));
工厂模式
<?php
namespace _1205;
//工厂模式:用于批量创建类的实例/对象
class Demo2{
//...
}
//假如要在多个文件中使用Demo2的实例,以前的做法就是美一个文件中引入并实例化
class Test1{
public function __construct($arg1){
echo '对象创建成功,参数是:'.$arg1;
}
}
class Test2{
public function __construct($arg1,$arg2){
echo '对象创建成功,参数是:'.implode(',',[$arg1,$arg2]);
}
}
class Test3{
public function __construct($arg1,$arg2,$arg3){
echo '对象创建成功,参数是:'.implode(',',[$arg1,$arg2,$arg3]);
}
}
//工厂类,专用于创建类实例
class Factory{
public static function create($className,...$argments){
return new $className(...$argments);
}
}
//类名::class:可以获得完整的类名,带命名空间
//用工厂类创建实例
Factory::create(Test1::class,100);
echo '<br>';
Factory::create(Test2::class,100,200);
echo '<br>';
Factory::create(Test3::class,100,200,300);
依赖注入
<?php
namespace _1205;
//依赖注入:解决对象调用之间的耦合度
//工作类
class Person{
//要依赖的外部对象
private $car = null;
//在构造方法中将依赖的外部对象全部实例化
//注入点放在构造方法中
public function __construct(){
$this->car = new Car();
}
//外部对象执行一个动作
public function work(){
return $this->car->drive();
}
}
//依赖的外部类
class Car{
public function drive(){
return '开车去上班';
}
}
//实例化类
$person = new Person();
echo $person->work();
echo '<hr>';
/*********************************/
class Person1{
//要依赖的外部对象
private $car = null;
//在构造方法中将依赖的外部对象全部实例化
//注入点放在构造方法中
public function __construct(Car1 $car){
$this->car = $car;
}
//外部对象执行一个动作
public function work(){
return $this->car->drive();
}
}
//依赖的外部类
class Car1{
public function drive(){
return '开小汽车去上班';
}
}
//实例化类
$car = new Car1();
$person = new Person1($car);
echo $person->work();
echo '<hr>';
服务容器的原理与实现
<?php
namespace _1205;
//引入需要用的类
require 'Product.php';
require 'Maker.php';
require 'Container.php';
class Client2{
public function show(Product $product,Maker $maker){
return $product->get($maker);
}
}
//客户端调用
//将类实例化绑定到容器中并实例化返回
$container = new Container();
//将实例化代码绑定要容器中
$container->bind('product',function (){return new Product();});
$container->bind('maker',function (){return new Maker();});
//创建类实例并返回
$product = $container->make('product');
$maker = $container->make('maker');
echo (new Client2())->show($product,$maker).'测试容器';
面向接口编程
<?php
namespace base;
//使用工厂类
//设置引用的外部类别名
use base\inc2\Car;
use base\inc2\Train;
use base\inc2\Plane;
use base\inc2\Ship;
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().'###去旅行';
}
}
//客户端调用
echo (new Travel3(new Car()))->travelModel().'<br>';
echo (new Travel3(new Train()))->travelModel().'<br>';
echo (new Travel3(new Plane()))->travelModel().'<br>';
echo (new Travel3(new Ship()))->travelModel().'<br>';
手抄作业
总结
一、单例模式:只允许存在一个实例对象,实例化得到的都是同一个对象,确保所有对象都访问同一个实例;三步:①、构造方法私有化,②、定义一个静态属性,③、对外提供获取实例的方法。
工厂模式:批量创建类实例化对象,类里面使用对外静态方法。
依赖注入:解决对象调用之间的耦合,区别在于注入点的不同
面向接口编程:在接口定义一连串的方法,再由具体初始类去实现该接口的方法,工作类中可以在构造方法参数中使用(接口 实现接口的类)