【深入PHP 面向对象】读书笔记(七)
来源:互联网 发布:足彩数据分析推荐 编辑:程序博客网 时间:2024/05/17 23:31
【简介】
单例模式:生成一个且只生成一个对象实例的特殊类。
工厂模式:构建创建者类的继承层级。
抽象模式:功能相关产品的创建。
原型模式:使用克隆来生成对象。
9.1 生成对象的问题和解决方法
定义一个员工的抽象类及其一个实现类:
abstract class Employee { protected $name; function __construct($name) { $this->name = $name; } abstract function fire();}class Minion extends Employee { function fire() { echo $this->name . "I'll clear my desk.<br>"; }}
再定义一个 Boss 的调用类:
class NastyBoss { private $employee = array(); function addEmployee($employeeName) { $this->employees[] = new Minion($employeeName); } function projectFails() { if (count($this->employees)>0) { $emp = array_pop($this->employees); $emp->fire(); } }}$boss = new NastyBoss();$boss -> addEmployee("harry");$boss -> addEmployee("bob");$boss -> addEmployee("mary");$boss -> projectFails();
并通过 NastBoss 的 addEmployee() 方法接受的名字字符来实例化新的 Minion 对象。NastyBoss 对象通过 projectFails() 方法删除一个 Minion 对象。
在这里我们直接在 NastyBoss 类中实例化 Minion 对象,代码的灵活性受到了限制,因为如果有 Employee 的其他子类的话,就无法直接调用。
如果 NastyBoss 对象可以使用 Employee 类的任何实例,代码的灵活性就会比较好。
在代码中,通过限制参数类型来解决这个问题,将addEmployee改成下面的方式:
function addEmployee(Employee $employeeName) { $this->employees[] = $employeeName; }
NastyBoss 类其他内容保持不变,并添加 CluedUp 类,如下:
class NastyBoss { private $employee = array(); function addEmployee(Employee $employeeName) { $this->employees[] = $employeeName; } function projectFails() { if (count($this->employees)>0) { $emp = array_pop($this->employees); $emp->fire(); } }}class CluedUp extends Employee { function fire() { echo $this->name . "I'll clear my lawyer.<br>"; }}
调用 addEmployee() 方法的时候,需要传入具体的对象参数:
$boss = new NastyBoss();$boss -> addEmployee(new Minion("harry"));$boss -> addEmployee(new CluedUp("bob"));$boss -> addEmployee(new Minion("mary"));$boss -> projectFails();
更好地解决方案「把对象实例化的工作委托出来」,委托一个独立的类或方法来生成 Employee 对象传递给 NastyBoss 的 addEmployee() 方法。下面给 Employee 类添加一个实现了对象创建策略的静态方法:
abstract class Employee { protected $name; private static $types = array('Minion', 'CluedUp', 'WellConnected'); static function recruit($name) { $num = rand(1, count(self::$types))-1; $class = self::$types[$num]; return new $class($name); } function __construct($name) { $this->name = $name; } abstract function fire();}class WellConnected extends Employee { function fire() { echo $this->name . "I'll clear my dad.<br>"; }}
通过一个姓名字符串来随机实例化具体的 Employee 子类,现在可以将实例化的细节委托给委托给Employee 类的 recruit() 方法。
$boss = new NastyBoss();$boss -> addEmployee(Employee::recruit("harry"));$boss -> addEmployee(Employee::recruit("bob"));$boss -> addEmployee(Employee::recruit("mary"));$boss -> projectFails();
9.2 单例模式
9.2.1 问题
在没有单例模式的情况下,以往的项目开发中,针对需要反复操作数据库的时候,就会产生大量的 new 操作,而每一次 new 操作都会消耗系统和内存的资源。
//初始化一个数据库句柄$db = new DB(...);//比如有个应用场景是添加一条用户信息$db->addUserInfo();......//然而我们要在另一地方使用这个用户信息,这时要用到数据库句柄资源,可能会这么做......function test() { $db = new DB(...); $db->getUserInfo();......有些朋友也许会说,可以直接使用global关键字! global $db;......
其中一个方案就是通过 global 去解决这个问题,但是 global 存在安全隐患。
通过单例模式,可以确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例,就可以在不引入全局变量的情况下,就能产生一个整个系统都能引用的对象。
9.3 工厂模式
9.3.1 简单工厂模式
在调用时看不到具体实例化对象的细节,而是通过一个接口实现实例化对象。
// 三种数据库类型 mysql sqlite sqlserverclass dbMysql { public function conn() { echo "connect to mysql."; }}class dbSqlite { public function conn() { echo "connect to sqlite."; }}class dbSqlserver { public function conn() { echo "connect to sqlserver."; }}// 工厂class Factory { public static createDb($type) { switch ($type) { case 'mysql': return new dbMysql(); break; case 'sqlite': return new dbSqlite(); break; case 'sqlserver': return new dbSqlserver(); break; default: throw new Exception("Error db type", 1); break; } }}// 调用生成对象$db = Factory::createDb("mysql");
在上面的例子中,只需要通过Factory::createDb()方法,并传入相应的数据库名称参数即可实例化一个数据库连接对象。
但是该方式扩展比较麻烦,比如还需要实现新增一个oracle的数据库连接对象,就需要修改Factory。
9.3.2 工厂方法模式
将简单工厂模式的工厂类进行抽象化,避免扩展时需要修改简单工厂模式中的工厂类。方便扩展、维护。
/* 定义一个数据库连接接口 */interface db{ public function conn();}/* 所有的数据库实例类都实现连接接口db */class dbMysql implements db{ public function conn() { echo "connect to mysql."; }}class dbSqlite implements db{ public function conn() { echo "connect to sqlite."; }}class dbSqlserver implements db{ public function conn() { echo "connect to sqlserver."; }}/* 定义一个创建数据库实例的类 */interface Factory { public function createDb();}/* 所有的工厂类都实现创建数据库的类 */class mysqlFactory implements Factory { public function createDb() { return new dbMysql(); }}class sqlite implements Factory { public function createDb() { return new dbSqlite(); }}class sqlServer implements Factory { public function createDb() { return new dbSqlserver(); }}
假设以上是已经封装好的对三个数据库(mysql、sqlite、sqlserver)的数据库连接类,现在需要扩展一个oralce的数据库的连接类,通过工厂方法模式可以在不改动前面已经封装好的情况下,完成扩展oracle数据库的工作。
/* 新增一个oracle数据库的时候,可以在不改动前面的封装好的代码的情况下,完成新增的需求 */class oracleFactory implements Factory { public function createDb() { return new dbOracle(); }}class dbOracle implements db { public function conn() { echo "connect to oracle."; }}
- 【深入PHP 面向对象】读书笔记(七)
- 【深入PHP 面向对象】读书笔记(一)
- 【深入PHP 面向对象】读书笔记(二)
- 【深入PHP 面向对象】读书笔记(三)
- 【深入PHP 面向对象】读书笔记(四)
- 【深入PHP 面向对象】读书笔记(五)
- 【深入PHP 面向对象】读书笔记(六)
- 【深入PHP 面向对象】读书笔记(八)
- 【深入PHP 面向对象】读书笔记(九)
- 【深入PHP 面向对象】读书笔记(十)
- 【深入PHP 面向对象】读书笔记(十一)
- 【深入PHP 面向对象】读书笔记(十二)
- 【深入PHP 面向对象】读书笔记(十三)
- 【深入PHP 面向对象】读书笔记(十四)
- 【深入PHP 面向对象】读书笔记(十五)
- 【深入PHP 面向对象】读书笔记(十六)
- 【深入PHP 面向对象】读书笔记(十七)
- 【深入PHP 面向对象】读书笔记(十八)
- java 中Pattern和Matcher详解
- 8月最新基于kubernetes的应用编排实践
- 题目1043:Day of Week
- Maven精品教程零散笔记(2017年8月25日18:54:33)
- dt dl dd 的英文含义
- 【深入PHP 面向对象】读书笔记(七)
- 安装g++
- 两个链表的第一个公共节点
- 开发工具修改data-XXX值,jq.data()取不到?
- mysql中的存储过程
- 复盘_8月——(第4周工作复盘)
- centos安装rzsz
- MYSQL-自动编号,主键,唯一约束与默认值
- NTP时间服务器,VPN