项目地址: 戳我
在软件工程中,建立型设计模式承担着对象建立的职责,尝试建立适合程序上下文的对象,对象建立设计模式的产生是因为软件工程设计的问题,具体说是向设计中增长复杂度,建立型设计模式解决了程序设计中对象建立的问题。php
建立一系列相关或依赖的对象,而不指定它们的具体类。一般建立的类都实现相同的接口。抽象工厂的客户端并不关心这些对象是如何建立的,它只知道它们是如何组合在一块儿的。前端
你能够在 GitHub 上查看代码git
Parser.phpgithub
<?php namespace DesignPatterns\Creational\AbstractFactory; interface Parser { public function parse(string $input): array; }
CsvParser.php数据库
<?php namespace DesignPatterns\Creational\AbstractFactory; class CsvParser implements Parser { const OPTION_CONTAINS_HEADER = true; const OPTION_CONTAINS_NO_HEADER = false; /** * @var bool */ private $skipHeaderLine; public function __construct(bool $skipHeaderLine) { $this->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.phpjson
<?php namespace DesignPatterns\Creational\AbstractFactory; class JsonParser implements Parser { public function parse(string $input): array { return json_decode($input, true); } }
ParserFactory.phpsegmentfault
<?php namespace DesignPatterns\Creational\AbstractFactory; class ParserFactory { public function createCsvParser(bool $skipHeaderLine): CsvParser { return new CsvParser($skipHeaderLine); } public function createJsonParser(): JsonParser { return new JsonParser(); } }
生成器的目的是将复杂对象的建立过程(流程)进行抽象,生成器表现为接口的形式。后端
在特定的状况下,好比若是生成器对将要建立的对象有足够多的了解,那么表明生成器的接口 interface
能够是一个抽象类(也就是说能够有必定的具体实现,就像众所周知的适配器模式)。设计模式
若是对象有复杂的继承树,理论上建立对象的生成器也一样具备复杂的继承树。缓存
提示:生成器一般具备流畅的接口,推荐阅读关于PHPUnit
的mock
生成器获取更好的理解。
你能够在 GitHub 上找到这些代码
Director.php
<?php namespace DesignPatterns\Creational\Builder; use DesignPatterns\Creational\Builder\Parts\Vehicle; /** * Director is part of the builder pattern. It knows the interface of the builder * and builds a complex object with the help of the builder * * You can also inject many builders instead of one to build more complex objects */ class Director { public function build(BuilderInterface $builder): Vehicle { $builder->createVehicle(); $builder->addDoors(); $builder->addEngine(); $builder->addWheel(); return $builder->getVehicle(); } }
BuilderInterface.php
<?php namespace DesignPatterns\Creational\Builder; use DesignPatterns\Creational\Builder\Parts\Vehicle; interface BuilderInterface { public function createVehicle(); public function addWheel(); public function addEngine(); public function addDoors(); public function getVehicle(): Vehicle; }
TruckBuilder.php
<?php namespace DesignPatterns\Creational\Builder; use DesignPatterns\Creational\Builder\Parts\Vehicle; class TruckBuilder implements BuilderInterface { /** * @var Parts\Truck */ private $truck; public function addDoors() { $this->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
<?php namespace DesignPatterns\Creational\Builder; use DesignPatterns\Creational\Builder\Parts\Vehicle; class CarBuilder implements BuilderInterface { /** * @var Parts\Car */ private $car; public function addDoors() { $this->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
<?php namespace DesignPatterns\Creational\Builder\Parts; abstract class Vehicle { /** * @var object[] */ private $data = []; /** * @param string $key * @param object $value */ public function setPart($key, $value) { $this->data[$key] = $value; } }
Parts/Truck.php
<?php namespace DesignPatterns\Creational\Builder\Parts; class Truck extends Vehicle { }
Parts/Car.php
<?php namespace DesignPatterns\Creational\Builder\Parts; class Engine { }
Parts/Engine.php
<?php namespace DesignPatterns\Creational\Builder\Parts; class Engine { }
Parts/Wheel.php
<?php namespace DesignPatterns\Creational\Builder\Parts; class Wheel { }
Parts/Door.php
<?php namespace DesignPatterns\Creational\Builder\Parts; class Door { }
SimpleFactory
的优势是您能够子类化它来实现建立对象的不一样方法。
对于简单的状况,这个抽象类可能只是一个接口。
这个模式是一个 "真正" 的设计模式,由于它遵循了依赖反转原则 Dependency Inversion Principle
众所周知这个 "D"
表明了真正的面向对象程序设计。
它意味着工厂方法类依赖于类的抽象,而不是具体将被建立的类,这是工厂方法模式与简单工厂模式和静态工厂模式最重要的区别。
你能够在 GitHub 上找到这些代码
Logger.php
<?php namespace DesignPatterns\Creational\FactoryMethod; interface Logger { public function log(string $message); }
StdoutLogger.php
<?php namespace DesignPatterns\Creational\FactoryMethod; class StdoutLogger implements Logger { public function log(string $message) { echo $message; } }
FileLogger.php
<?php namespace DesignPatterns\Creational\FactoryMethod; class FileLogger implements Logger { /** * @var string */ private $filePath; public function __construct(string $filePath) { $this->filePath = $filePath; } public function log(string $message) { file_put_contents($this->filePath, $message . PHP_EOL, FILE_APPEND); } }
LoggerFactory.php
<?php namespace DesignPatterns\Creational\FactoryMethod; interface LoggerFactory { public function createLogger(): Logger; }
StdoutLoggerFactory.php
<?php namespace DesignPatterns\Creational\FactoryMethod; class StdoutLoggerFactory implements LoggerFactory { public function createLogger(): Logger { return new StdoutLogger(); } }
FileLoggerFactory.php
<?php namespace DesignPatterns\Creational\FactoryMethod; class FileLoggerFactory implements LoggerFactory { /** * @var string */ private $filePath; public function __construct(string $filePath) { $this->filePath = $filePath; } public function createLogger(): Logger { return new FileLogger($this->filePath); } }
多例模式已经被考虑列入到反模式中!请使用依赖注入得到更好的代码可测试性和可控性!
使类仅有一个命名的对象的集合可供使用,像单例模式可是有多个实例。
MySQL
,另外一个链接SQLite
你能够在 GitHub 上找到这些代码
Multiton.php
<?php namespace DesignPatterns\Creational\Multiton; final class Multiton { const INSTANCE_1 = '1'; const INSTANCE_2 = '2'; /** * @var Multiton[] */ private static $instances = []; /** * this is private to prevent from creating arbitrary instances */ private function __construct() { } public static function getInstance(string $instanceName): Multiton { if (!isset(self::$instances[$instanceName])) { self::$instances[$instanceName] = new self(); } return self::$instances[$instanceName]; } /** * prevent instance from being cloned */ private function __clone() { } /** * prevent instance from being unserialized */ private function __wakeup() { } }
对象池设计模式 是建立型设计模式,它会对新建立的对象应用一系列的初始化操做,让对象保持当即可以使用的状态 - 一个存放对象的 “池子” - 而不是对对象进行一次性的的使用(建立并使用,完成以后当即销毁)。对象池的使用者会对对象池发起请求,以指望获取一个对象,并使用获取到的对象进行一系列操做,当使用者对对象的使用完成以后,使用者会将由对象池的对象建立工厂建立的对象返回给对象池,而不是用完以后销毁获取到的对象。
对象池在某些状况下会带来重要的性能提高,好比耗费资源的对象初始化操做,实例化类的代价很高,但每次实例化的数量较少的状况下。对象池中将被建立的对象会在真正被使用时被提早建立,避免在使用时让使用者浪费对象建立所需的大量时间(好比在对象某些操做须要访问网络资源的状况下)从池子中取得对象的时间是可预测的,但新建一个实例所需的时间是不肯定。
总之,对象池会为你节省宝贵的程序执行时间,好比像数据库链接,socket
链接,大量耗费资源的表明数字资源的对象,像字体或者位图。不过,在特定状况下,简单的对象建立池(没有请求外部的资源,仅仅将自身保存在内存中)或许并不会提高效率和性能,这时候,就须要使用者酌情考虑了。
你能够在 GitHub 上找到这些代码
WorkerPool.php
<?php namespace DesignPatterns\Creational\Pool; class WorkerPool implements \Countable { /** * @var StringReverseWorker[] */ private $occupiedWorkers = []; /** * @var StringReverseWorker[] */ private $freeWorkers = []; public function get(): StringReverseWorker { if (count($this->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
<?php namespace DesignPatterns\Creational\Pool; class StringReverseWorker { /** * @var \DateTime */ private $createdAt; public function __construct() { $this->createdAt = new \DateTime(); } public function run(string $text) { return strrev($text); } }
经过建立一个原型对象,而后复制原型对象来避免经过标准的方式建立大量的对象产生的开销(new Foo()
)。
ORM
获取1,000,000行数据库记录而后建立每一条记录对应的对象实体)你能够在 GitHub 上找到这些代码
BookPrototype.php
<?php namespace DesignPatterns\Creational\Prototype; abstract class BookPrototype { /** * @var string */ protected $title; /** * @var string */ protected $category; abstract public function __clone(); public function getTitle(): string { return $this->title; } public function setTitle($title) { $this->title = $title; } }
BarBookPrototype.php
<?php namespace DesignPatterns\Creational\Prototype; class BarBookPrototype extends BookPrototype { /** * @var string */ protected $category = 'Bar'; public function __clone() { } }
FooBookPrototype.php
<?php namespace DesignPatterns\Creational\Prototype; class FooBookPrototype extends BookPrototype { /** * @var string */ protected $category = 'Foo'; public function __clone() { } }
它与静态工厂不一样,由于它不是静态的。所以,能够有多个参数化的工厂,能够子类化它,也能够模拟它。它老是比静态工厂更受欢迎!
你能够在 GitHub 上找到这些代码
SimpleFactory.php
<?php namespace DesignPatterns\Creational\SimpleFactory; class SimpleFactory { public function createBicycle(): Bicycle { return new Bicycle(); } }
Bicycle.php
<?php namespace DesignPatterns\Creational\SimpleFactory; class Bicycle { public function driveTo(string $destination) { } }
$factory = new SimpleFactory(); $bicycle = $factory->createBicycle(); $bicycle->driveTo('Paris');
使应用中只存在一个对象的实例,而且使这个单实例负责全部对该对象的调用。
你能够在 GitHub 上找到这些代码
Singleton.php
<?php namespace DesignPatterns\Creational\Singleton; final class Singleton { /** * @var Singleton */ private static $instance; /** * gets the instance via lazy initialization (created on first usage) */ public static function getInstance(): Singleton { if (null === static::$instance) { static::$instance = new static(); } return static::$instance; } /** * is not allowed to call from outside to prevent from creating multiple instances, * to use the singleton, you have to obtain the instance from Singleton::getInstance() instead */ private function __construct() { } /** * prevent the instance from being cloned (which would create a second instance of it) */ private function __clone() { } /** * prevent from being unserialized (which would create a second instance of it) */ private function __wakeup() { } }
和抽象工厂相似,静态工厂模式用来建立一系列互相关联或依赖的对象,和抽象工厂模式不一样的是静态工厂模式只用一个静态方法就解决了全部类型的对象建立,一般被命名为 Factory
或者 Generators
zend_cache_
后端或 _Frontend
使用工厂方法建立缓存后端和前端你能够在 GitHub 上找到这些代码
StaticFactory.php
<?php namespace DesignPatterns\Creational\StaticFactory; /** * Note1: Remember, static means global state which is evil because it can't be mocked for tests * Note2: Cannot be subclassed or mock-upped or have multiple different instances. */ final class StaticFactory { /** * @param string $type * * @return Formatter */ public static function factory(string $type): Formatter { if ($type == 'number') { return new FormatNumber(); } elseif ($type == 'string') { return new FormatString(); } throw new \InvalidArgumentException('Unknown format given'); } }
Formatter.php
<?php namespace DesignPatterns\Creational\StaticFactory; interface Formatter { public function format(string $input): string; }
FormatString.php
<?php namespace DesignPatterns\Creational\StaticFactory; class FormatString implements Formatter { public function format(string $input): string { return $input; } }
FormatNumber.php
<?php namespace DesignPatterns\Creational\StaticFactory; class FormatNumber implements Formatter { public function format(string $input): string { return number_format($input); } }