1. 将课堂代码全部上机操作至少一遍以上
单例模式(以pdo操作举例)
<?php
//单例模式
//声明命名空间
namespace _1210;
class Single
{
//构造方法私有后,使外部不能实例化类
private function __construct()
{
}
//无法使用clone方法
private function __clone()
{
// TODO: Implement __clone() method.
}
//类的实例,先赋初值
public static $instance = null;
public static function getInstance()
{
//判断当前类是否已经实例化了,没有就实例化
if(is_null(self::$instance)){
self::$instance = new self();
}
//已经实例化就返回它
return self::$instance;
}
}
$obj1 = Single::getInstance();
$obj2 = Single::getInstance();
var_dump($obj1 === $obj2);
//创建的两个对象一样--单个实例--单例模式
echo '<hr/>';
//应用场景,以数据库连接举例
class Db{
private function __construct(...$connectParams)
{
$dsn = $connectParams[0];
$username = $connectParams[1];
$password = $connectParams[2];
self::$pdo = new \PDO($dsn,$username,$password);
}
public static $pdo = null;
public static function getInstance(...$connectParams)
{
//判断是否实例化了,empty?
if(is_null(self::$pdo)){
//与上面不同的是,这里是构造函数,不用返回self::$instance
new self(...$connectParams);
}
return self::$pdo;
}
}
echo '<br/>';
$connectParams = ['mysql:host=localhost;dbname=anguoguo','root','root'];
$pdo = Db::getInstance(...$connectParams);
print_r($pdo->query('SELECT * FROM `movies`')->fetchAll());
工厂模式
<?php
//工厂模式--流水线生产类的实例
namespace _1210;
//声明工厂类,里面有生产方法,用的是静态方法--new一个实例
class Factory{
public static function create($className,...$params){
return new $className(...$params);
}
}
//声明商品类,有各自的方法
class Goods1{
public function __construct($para1)
{
echo '商品1创建成功,参数为: ' . $para1;
}
}
class Goods2{
public function __construct($para1,$para2)
{
echo '商品2创建成功,参数为: ' . implode(',',[$para1,$para2]);
}
}
class Goods3{
public function __construct($para1,$para2,$para3)
{
echo '商品3创建成功,参数为: ' . implode(',',[$para1,$para2,$para3]);
//implode:数组转为字符串,以,为分隔依据,相对的是explode字符串转为数组,也以第一个参数为划分依据
}
}
//静态方法调用方式,类作为参数时的写法xx::class
Factory::create(Goods1::class,'甲');
echo '<hr/>';
Factory::create(Goods2::class,'甲','乙');
echo '<hr/>';
Factory::create(Goods3::class,'甲','乙','丙');
依赖注入(DI)
<?php
namespace _1210;
//依赖注入:Dependency Injection解决对象调用之间的耦合
class Someone{
private $football = null;//这个类依赖的外部类的对象
public function __construct()
{
$this->football = new Football();//此处将外部对象实例化,此处为外部对象注入点
}
public function relax(){
return $this->football->play();//外部对象执行一个操作
}
}
//依赖的外部类,Football
class Football{
public function play(){
return '休息时踢足球';
}
}
$someone = new Someone();
echo $someone->relax();
echo '<hr/>';
/***************************************************/
//也可以在外部$football = new Football(),前面构造函数处就不用new Football(),直接$football
容器类(将实例与方法放进容器,再取出生成实例)
产品:
<?php
namespace _1210;
class Product
{
public function get(Maker $maker){
return '这辆小钢炮是由:<span style="color:lightblue;font-weight: bolder"> ' .
$maker->get() . '</span>生产';
}
}
生产商:
<?php
namespace _1210;
class Maker{
public function get(){
return '福特';
}
}//生产商
容器:
<?php
namespace _1210;
use Closure;//要用闭包
class Container{
protected $instance = [];//instance例子,即表示实例数组(容器)
//类实例,实例方法绑定到容器中(数组)
public function bind($alias,Closure $process){
$this->instance[$alias] = $process;
}
//从容器中取出实例化过程的闭包,执行它
public function make($alias){
return $this->instance[$alias]();//即$process(),,()代表执行
}
}
容器使用:
<?php
namespace _1210;
require 'Product.php';
require 'Maker.php';//引入外部两个文件,为什么不use类呢
require 'Container.php';//引入了容器类
class Client2{
public function show(Product $product,Maker $maker){
//之前实例化的过程交给容器make,两个参数需要在这里传入吗,与类中参数相关
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');
//以上按照Container类中的流程实例化,绑定,取出执行
echo (new Client2())->show($product,$maker);//称为客户端调用,同时把类实例化,这里是和实例化后的参数相关
面向接口编程
接口(给类定个规范):
<?php
//与inc1比多了接口
namespace base\inc2;
// 休闲方式的接口
interface iBall
{
public function play();//抽象的
}
休闲类(三个,生效自接口)
<?php
//01.Baseball类
namespace base\inc2;
class Baseball implements iBall {
public function play(){
return '打棒球';
}
}
//02.Basketball类
class Basketball implements iBall{
public function play(){
return '玩篮球';
}
}
//03.Football类
class Football implements iBall {
public function play(){
return '玩足球';
}
}
自动加载函数(方便引入多个文件)
<?php
spl_autoload_register(function ($className){//spl_autoload_register函数的参数是一个回调函数,调用该函数会将注册的加载函数放入autoload函数队列中
$path = str_replace('\\','/',$className);
require dirname(__DIR__) . DIRECTORY_SEPARATOR . $path . '.php';
});//自动加载函数,自动加载当前同目录下的$path.php
用法:
<?php
//说明面向接口编程
namespace base;
use base\inc2\Baseball;
use base\inc2\Basketball;
use base\inc2\Football;
use base\inc2\iBall;
//在实例化以上类时,IDE会自动use
require __DIR__ . '/autoload.php';//自动加载,不用require一堆文件了
class Relax3{
//球类
private $ball;
//构造方法
public function __construct(iBall $ball)
{
$this->ball = $ball;
}
//调用外部一个依赖对象
public function relaxModel(){
return $this->ball->play() . ' : 通过接口去放松';
}
}
//客户端调用
$football =new Football();
echo (new Relax3($football))->relaxModel(), '<br/>';
echo (new Relax3(new Baseball()))->relaxModel(), '<br/>';//直接在调用参数的时候实例化类
echo (new Relax3(new Basketball()))->relaxModel(), '<br/>';
2. 手写课堂笔记:1205.md
朱老师,说明一下用作业本书写舒服一点,肯定有装订的。
总结
单例模式:实例就一个,常见于使用PDO建立数据模型
工厂模式:生产N个实例
依赖注入(DI):内部调用外部实例,就不要在内部实例化了,会加重类间耦合,最好在外部实例化,然后将实例作为参数传到调用类的构造方法里
容器:实例和实例化方法都放进去,要用时再拿出来
面向接口:接口是规范类的,使用抽象方法