【搬运于GitHub开源项目DesignPatternsPHP】
项目地址: 戳我
1、创建型设计模式
在软件工程中,创建型设计模式承担着对象创建的职责,尝试创建适合程序上下文的对象,对象创建设计模式的产生是由于软件工程设计的问题,具体说是向设计中增加复杂度,创建型设计模式解决了程序设计中对象创建的问题。
1.1 抽象工厂
1.1.1 目的
创建一系列相关或依赖的对象,而不指定它们的具体类。通常创建的类都实现相同的接口。抽象工厂的客户端并不关心这些对象是如何创建的,它只知道它们是如何组合在一起的。
1.1.2 UML图
1.1.3 代码
你可以在 GitHub 上查看代码
Parser.php
CsvParser.php
skipHeaderLine = $skipHeaderLine;
}
public function parse(string $input): array
{
$headerWasParsed = false;
$parsedLines = [];
foreach (explode(PHP_EOL, $input) as $line) {
if (!$headerWasParsed && $this->skipHeaderLine === self::OPTION_CONTAINS_HEADER) {
$headerWasParsed = true;
continue;
}
$parsedLines[] = str_getcsv($line);
}
return $parsedLines;
}
}
JsonParser.php
ParserFactory.php
1.2 生成器模式
1.2.1 目的
生成器的目的是将复杂对象的创建过程(流程)进行抽象,生成器表现为接口的形式。
在特定的情况下,比如如果生成器对将要创建的对象有足够多的了解,那么代表生成器的接口 interface
可以是一个抽象类(也就是说可以有一定的具体实现,就像众所周知的适配器模式)。
如果对象有复杂的继承树,理论上创建对象的生成器也同样具有复杂的继承树。
提示:生成器通常具有流畅的接口,推荐阅读关于PHPUnit
的mock
生成器获取更好的理解。
1.2.2 例子
- PHPUnit: Mock 生成器
1.2.3 UML图
1.2.4 代码
你可以在 GitHub 上找到这些代码
Director.php
createVehicle();
$builder->addDoors();
$builder->addEngine();
$builder->addWheel();
return $builder->getVehicle();
}
}
BuilderInterface.php
TruckBuilder.php
truck->setPart('rightDoor', new Parts\Door());
$this->truck->setPart('leftDoor', new Parts\Door());
}
public function addEngine()
{
$this->truck->setPart('truckEngine', new Parts\Engine());
}
public function addWheel()
{
$this->truck->setPart('wheel1', new Parts\Wheel());
$this->truck->setPart('wheel2', new Parts\Wheel());
$this->truck->setPart('wheel3', new Parts\Wheel());
$this->truck->setPart('wheel4', new Parts\Wheel());
$this->truck->setPart('wheel5', new Parts\Wheel());
$this->truck->setPart('wheel6', new Parts\Wheel());
}
public function createVehicle()
{
$this->truck = new Parts\Truck();
}
public function getVehicle(): Vehicle
{
return $this->truck;
}
}
CarBuilder.php
car->setPart('rightDoor', new Parts\Door());
$this->car->setPart('leftDoor', new Parts\Door());
$this->car->setPart('trunkLid', new Parts\Door());
}
public function addEngine()
{
$this->car->setPart('engine', new Parts\Engine());
}
public function addWheel()
{
$this->car->setPart('wheelLF', new Parts\Wheel());
$this->car->setPart('wheelRF', new Parts\Wheel());
$this->car->setPart('wheelLR', new Parts\Wheel());
$this->car->setPart('wheelRR', new Parts\Wheel());
}
public function createVehicle()
{
$this->car = new Parts\Car();
}
public function getVehicle(): Vehicle
{
return $this->car;
}
}
Parts/Vehicle.php
data[$key] = $value;
}
}
Parts/Truck.php
Parts/Car.php
Parts/Engine.php
Parts/Wheel.php
Parts/Door.php
1.3 工厂方法
1.3.1 目的
SimpleFactory
的优点是您可以子类化它来实现创建对象的不同方法。
对于简单的情况,这个抽象类可能只是一个接口。
这个模式是一个 "真正" 的设计模式,因为它遵循了依赖反转原则 Dependency Inversion Principle
众所周知这个 "D"
代表了真正的面向对象程序设计。
它意味着工厂方法类依赖于类的抽象,而不是具体将被创建的类,这是工厂方法模式与简单工厂模式和静态工厂模式最重要的区别。
1.3.2 UML图
1.3.3 代码
你可以在 GitHub 上找到这些代码
Logger.php
StdoutLogger.php
FileLogger.php
filePath = $filePath;
}
public function log(string $message)
{
file_put_contents($this->filePath, $message . PHP_EOL, FILE_APPEND);
}
}
LoggerFactory.php
StdoutLoggerFactory.php
FileLoggerFactory.php
filePath = $filePath;
}
public function createLogger(): Logger
{
return new FileLogger($this->filePath);
}
}
1.4 多例
多例模式已经被考虑列入到反模式中!请使用依赖注入获得更好的代码可测试性和可控性!
1.4.1 目的
使类仅有一个命名的对象的集合可供使用,像单例模式但是有多个实例。
1.4.2 例子
- 2 个数据库连接,比如,一个连接
MySQL
,另一个连接SQLite
- 多个日志记录器(一个记录调试信息,另一个记录错误信息)
1.4.3 UML 图
1.4.4 代码
你可以在 GitHub 上找到这些代码
Multiton.php
1.5 对象池
1.5.1 目的
对象池设计模式 是创建型设计模式,它会对新创建的对象应用一系列的初始化操作,让对象保持立即可使用的状态 - 一个存放对象的 “池子” - 而不是对对象进行一次性的的使用(创建并使用,完成之后立即销毁)。对象池的使用者会对对象池发起请求,以期望获取一个对象,并使用获取到的对象进行一系列操作,当使用者对对象的使用完成之后,使用者会将由对象池的对象创建工厂创建的对象返回给对象池,而不是用完之后销毁获取到的对象。
对象池在某些情况下会带来重要的性能提升,比如耗费资源的对象初始化操作,实例化类的代价很高,但每次实例化的数量较少的情况下。对象池中将被创建的对象会在真正被使用时被提前创建,避免在使用时让使用者浪费对象创建所需的大量时间(比如在对象某些操作需要访问网络资源的情况下)从池子中取得对象的时间是可预测的,但新建一个实例所需的时间是不确定。
总之,对象池会为你节省宝贵的程序执行时间,比如像数据库连接,socket
连接,大量耗费资源的代表数字资源的对象,像字体或者位图。不过,在特定情况下,简单的对象创建池(没有请求外部的资源,仅仅将自身保存在内存中)或许并不会提升效率和性能,这时候,就需要使用者酌情考虑了。
1.5.2 UML图
1.5.3 代码
你可以在 GitHub 上找到这些代码
WorkerPool.php
freeWorkers) == 0) {
$worker = new StringReverseWorker();
} else {
$worker = array_pop($this->freeWorkers);
}
$this->occupiedWorkers[spl_object_hash($worker)] = $worker;
return $worker;
}
public function dispose(StringReverseWorker $worker)
{
$key = spl_object_hash($worker);
if (isset($this->occupiedWorkers[$key])) {
unset($this->occupiedWorkers[$key]);
$this->freeWorkers[$key] = $worker;
}
}
public function count(): int
{
return count($this->occupiedWorkers) + count($this->freeWorkers);
}
}
StringReverseWorker.php
createdAt = new \DateTime();
}
public function run(string $text)
{
return strrev($text);
}
}
1.6 原型模式
1.6.1 目的
通过创建一个原型对象,然后复制原型对象来避免通过标准的方式创建大量的对象产生的开销(new Foo()
)。
1.6.2 例子
- 大量的数据对象(比如通过
ORM
获取1,000,000行数据库记录然后创建每一条记录对应的对象实体)
1.6.3 UML图
1.6.4 代码
你可以在 GitHub 上找到这些代码
BookPrototype.php
title;
}
public function setTitle($title)
{
$this->title = $title;
}
}
BarBookPrototype.php
FooBookPrototype.php
1.7 简单工厂
1.7.1 目的
它与静态工厂不同,因为它不是静态的。因此,可以有多个参数化的工厂,可以子类化它,也可以模拟它。它总是比静态工厂更受欢迎!
1.7.2 UML图
1.7.3 代码
你可以在 GitHub 上找到这些代码
SimpleFactory.php
Bicycle.php
1.7.4 使用
$factory = new SimpleFactory();
$bicycle = $factory->createBicycle();
$bicycle->driveTo('Paris');
1.8 单例模式
1.8.1 目标
使应用中只存在一个对象的实例,并且使这个单实例负责所有对该对象的调用。
1.8.2 例子
- 数据库连接器
- 日志记录器 (可能有多个实例,比如有多个日志文件因为不同的目的记录不同到的日志)
- 应用锁文件 (理论上整个应用只有一个锁文件)
1.8.3 UML图
1.8.4 代码
你可以在 GitHub 上找到这些代码
Singleton.php
1.9 静态工厂
1.9.1 目的
和抽象工厂类似,静态工厂模式用来创建一系列互相关联或依赖的对象,和抽象工厂模式不同的是静态工厂模式只用一个静态方法就解决了所有类型的对象创建,通常被命名为 Factory
或者 Generators
1.9.2 例子
- Zend Framework:
zend_cache_
后端或_Frontend
使用工厂方法创建缓存后端和前端
1.9.3 UML图
1.9.4 代码
你可以在 GitHub 上找到这些代码
StaticFactory.php
Formatter.php
FormatString.php
FormatNumber.php
相关文章:
PHP设计模式范例 — DesignPatternsPHP(2)结构型设计模式