批改状态:合格
老师批语:设计模式有很多, 咱们课堂时间有限, 无法一一举例, 更多的还需要同学私下努力
在数据库访问时,数据库对外提供的连接数是有限的,因此一个用户只需创建一个链接就可以,采用“单例模式”设计,判断某个类是否已经创建过实例,可实现这个目的。下面演示“单例模式”的原理
<?php//文件: src\inc\Singleten.php;//没有传入参数的情况namespace src\inc;class Singleten{private static $selfObj;//禁用构造方法private function __construct(){//...}//禁用cloneprivate function __clone(){//...}//判断是否已创建过类实例public static function getInstance(){if (is_null(static::$selfObj)) {static::$selfObj=new self();}return static::$selfObj;}}$pdo=Singleten::getInstance();$pdo1=Singleten::getInstance();var_dump($pdo===$pdo1);

在编程过程中,某个.php文件常常要通过(new)关键字引用多个类的实例,当某个类被多个.php文件调用,而突然不得不改名时,意味着所有调用了该类的文件全部都得重新更正调用的类名称。采用工厂模式编程,可解决这个问题。下面演示工厂模式的两种模式:普通工厂 和 抽象工厂 。
线上支付和线下支付为例)
<?php//文件:src\inc1\Online.php;namespace src\inc1;class Online{public function purchase(){echo '线上转帐';}}
<?php//文件:src\inc1\Offline.php;namespace src\inc1;class Offline{public function purchase(){echo '线下现金支付';}}
<?php//文件:src\inc1\Factory.php;namespace src\inc1;class Factory{private static $shopWays;public static function getInstance(string $shopWays){switch (strtolower($shopWays)):case 'online':static::$shopWays = new Online();break;case 'offline':static::$shopWays = new Offline();break;endswitch;return static::$shopWays;}}
<?php//文件:src\inc1\Shopping.php;namespace src\inc1;class Shopping{public static function purchase($shopWays){Factory::getInstance($shopWays)->purchase();}}
<?php//文件:src\inc1\Main.php;namespace src\inc1;require '..\autoload.php';$shopWays=Shopping::purchase('online');echo '<br>';$shopWays=Shopping::purchase('offline');

===================================================================
<?php//文件:src\inc2\Online.php;namespace src\inc2;class Online implements IShopping{public function purchase(){echo '线上转帐';}}
<?php//文件:src\inc2\Offline.php;namespace src\inc2;class Offline implements IShopping{public function purchase(){echo '线下现金支付';}}
<?php//文件: src\inc2\IShopping.phpnamespace src\inc2;interface IShopping{public function purchase();}
<?php//文件: src\inc2\Shopping.phpnamespace src\inc2;class Shopping{public static function purchase(IShopping $ishopping){$ishopping->purchase();}}
<?php//文件: src\inc2\Main.phpnamespace src\inc2;require '..\autoload.php';$shopWays=Shopping::purchase(new Online());echo '<br>';$shopWays=Shopping::purchase(new Offline());

===================================================================
下面以数据库访问为例结合单例模式演示抽象工厂的原理:分别以PDO和Mysqli方式进行数据库查询select()操作。
<?php//文件: src\inc\IDataBase.php;namespace src\inc;interface IDataBase{public function select(): array;}
<?php//文件: src\inc\Mysqli.php;namespace src\inc;class Mysqli implements IDataBase {private static $mysqli=null;private static $selfObj=null;private function __construct(...$arguments){static::$mysqli = new \Mysqli(...$arguments);}//类实例public static function getInstance(...$argument){if (is_null(static::$selfObj)) {static::$selfObj=new self(...$argument);}return static::$selfObj;}//禁用cloneprivate function __clone(){//...}//设置变量public function __set(string $name, $value){$this->{$name}=$value;}//查询public function select(): array{return static::$mysqli->query($this->sql)->fetch_All(MYSQLI_ASSOC);}}
<?php//文件: src\inc\PDO.php;namespace src\inc;class PDO implements IDataBase{private static $pdo=null;private static $selfObj=null;private function __construct(...$arguments){static::$pdo = new \PDO(...$arguments);}//类实例public static function getInstance(...$argument){if (is_null(static::$selfObj)) {static::$selfObj=new self(...$argument);}return static::$selfObj;}//禁用cloneprivate function __clone(){//...}public function __set(string $name, $value){$this->{$name}=$value;}public function select(): array{return static::$pdo->query($this->sql)->fetchAll(\PDO::FETCH_ASSOC);}}
<?php//文件: src\inc\DataBase.php;namespace src\inc;class DataBase{public static function select(IDataBase $idatabase): array{return $idatabase->select();}}
<?php//文件 src\autoload.php;spl_autoload_register(function ($clasName) {$file = str_replace('\\', DIRECTORY_SEPARATOR, (dirname(__DIR__) . '\\' . $clasName)) . '.php';file_exists($file) ? require $file : '加载失败,文件不存在';});
<?php//文件: src\inc\Main.php;namespace src\inc;require '..\autoload.php';//Mysqli查询`phpedu`.`staffs`表中第1条记录$mysqli = Mysqli::getInstance('db.io', 'root', 'root', 'phpedu');$mysqli->sql='SELECT * FROM `staffs`;';echo "数据库(`phpedu`).表(`staffs`)首条记录:";echo '<pre>' . print_r(DataBase::select($mysqli)[0],true) . '</pre>';//PDO查询`phpedu`.`users`表中第1条记录$pdo = PDO::getInstance('mysql:host=db.io;dbname=phpedu', 'root', 'root');$pdo->sql='SELECT * FROM `users`;';echo "数据库(`phpedu`).表(`users`)首条记录:";echo '<pre>' . print_r(DataBase::select($pdo)[0],true) . '</pre>';

单例模式,通过将构造方法(construct())、克隆方法(clone())从外部禁用,而从内部控制实例化的方式,有效避免类的重复实例化.工厂模式是将原构造方法中实例化依赖对象的过程,交给工厂类完成。其中,普通工厂模式,通过判断条件,根据输入不同的类别实例化不同的类,将原来的依赖多个类变成依赖1个类; 抽象工厂模式,运用接口的方式来实现,与普通工厂相比,代码量更少,灵活性更高,出错概率低 ,维护更方便。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号