PHP设计模式的创建型有哪几种?相信很多新手小白对PHP设计模式的创建型的了解处于懵懂状态,通过这篇文章的总结,希望你能有所收获。
我们学习的设计模式分为三类:创建者模式、结构型模式、行为型模式;创建型模式与对象的创建有关;结构型模式处理类或对象的组合;而行为型模式是对类或对象怎样交互和怎样分配职责进行描述;
PHP 设计模式的创建型包括:单例模式(Singleton), 多例模式(Multiton), 工厂方法模式(Factory Method), 抽象工厂模式(Abstract Factory), 简单工厂模式(Simple Factory), 原型模式(Prototype), 对象池模式(Pool), 建造者模式(Builder)
(一)单例模式(Singleton)
● 定义
保证一个类只有一个实例,并且提供一个访问它的全局访问点。系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
● 代码示例
class Singleton
{
/**
* @var Singleton
*/
private static $instance;
/**
* 不允许从外部调用以防止创建多个实例
* 要使用单例,必须通过 Singleton::getInstance() 方法获取实例
*/
private function __construct()
{
}
/**
* 通过懒加载获得实例(在第一次使用的时候创建)
*/
public static function getInstance(): Singleton
{
if (null === static::$instance) {
static::$instance = new static();
}
return static::$instance;
}
/**
* 防止实例被克隆(这会创建实例的副本)
*/
private function __clone()
{
}
/**
* 防止反序列化(这将创建它的副本)
*/
private function __wakeup()
{
}
}
(二)多例模式(Multiton)
● 定义
在多例模式中,多例类可以有多个实例,而且多例类必须自己创建、管理自己的实例,并向外界提供自己的实例。1. 通过实例容器保存容器。2. 利用私有构造阻止外部构造。3. 提供getInstantce()方法获取实例.
● 代码示例 两个对象通过一个类进行多次实例化
abstract class Multiton {
private static $instances = array();
public static function getInstance() {
$key = get_called_class() . serialize(func_get_args());
if (!isset(self::$instances[$key])) {
$rc = new ReflectionClass(get_called_class());
self::$instances[$key] = $rc->newInstanceArgs(func_get_args());
}
return self::$instances[$key];
}
/**
* 该私有对象阻止实例被克隆
*/
private function __clone()
{
}
/**
* 该私有方法阻止实例被序列化
*/
private function __wakeup()
{
}
}
class Hello extends Multiton {
public function __construct($string = 'World') {
echo "Hello $string\n";
}
}
class GoodBye extends Multiton {
public function __construct($string = 'my', $string2 = 'darling') {
echo "Goodbye $string $string2\n";
}
}
$a = Hello::getInstance('World');
$b = Hello::getInstance('bob');
// $a !== $b
$c = Hello::getInstance('World');
// $a === $c
$d = GoodBye::getInstance();
$e = GoodBye::getInstance();
// $d === $e
$f = GoodBye::getInstance('your');
// $d !== $f
(三)工厂方法模式(Factory Method)
● 定义
将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一个类
● 代码示例 : 小成有一间塑料加工厂(仅生产 A 类产品);随着客户需求的变化,客户需要生产 B 类产品。改变原有塑料加工厂的配置和变化非常困难,假设下一次客户需要再发生变化,再次改变将增大非常大的成本;小成决定置办塑料分厂 B 来生产 B 类产品。
abstract class Product{
public abstract function Show();
}
//具体产品A类
class ProductA extends Product{
public function Show() {
echo "生产出了产品A";
}
}
//具体产品B类
class ProductB extends Product{
public function Show() {
echo "生产出了产品B";
}
}
abstract class Factory{
public abstract function Manufacture();
}
//工厂A类 - 生产A类产品
class FactoryA extends Factory{
public function Manufacture() {
return new ProductA();
}
}
//工厂B类 - 生产B类产品
class FactoryB extends Factory{
public function Manufacture() {
return new ProductB();
}
}
(四)抽象工厂模式(Abstract Factory)
● 定义
在不指定具体类的情况下创建一系列相关或依赖对象。 通常创建的类都实现相同的接口。 抽象工厂的客户并不关心这些对象是如何创建的,它只是知道它们是如何一起运行的。
● 代码示例 : 有两个工厂,A 工厂负责运输,B 工厂生产数码产品.
interface Product
{
public function calculatePrice(): int;
}
class ShippableProduct implements Product
{
/**
* @var float
*/
private $productPrice;
/**
* @var float
*/
private $shippingCosts;
public function __construct(int $productPrice, int $shippingCosts)
{
$this->productPrice = $productPrice;
$this->shippingCosts = $shippingCosts;
}
public function calculatePrice(): int
{
return $this->productPrice + $this->shippingCosts;
}
}
class DigitalProduct implements Product
{
/**
* @var int
*/
private $price;
public function __construct(int $price)
{
$this->price = $price;
}
public function calculatePrice(): int
{
return $this->price;
}
}
class ProductFactory
{
const SHIPPING_COSTS = 50;
public function createShippableProduct(int $price): Product
{
return new ShippableProduct($price, self::SHIPPING_COSTS);
}
public function createDigitalProduct(int $price): Product
{
return new DigitalProduct($price);
}
}
(五)简单工厂模式(Simple Factory)
● 定义
简单工厂模式是一个精简版的工厂模式。工厂角色-具体产品-抽象产品
● 代码示例 :
一个农场,要向市场销售水果。农场里有三种水果 苹果、葡萄,我们设想:1、水果有多种属性,每个属性都有不同,但是,他们有共同的地方 | 生长、种植、收货、吃。将来有可能会增加新的水果、我们需要定义一个接口来规范他们必须实现的方法.
interface fruit{
/**
* 生长
*/
public function grow();
/**
* 种植
*/
public function plant();
/**
* 收获
*/
public function harvest();
/**
* 吃
*/
public function eat();
}
class apple implements fruit{
//苹果树有年龄
private $treeAge;
//苹果有颜色
private $color;
public function grow(){
echo "grape grow";
}
public function plant(){
echo "grape plant";
}
public function harvest(){
echo "grape harvest";
}
public function eat(){
echo "grape eat";
}
//取苹果树的年龄
public function getTreeAge(){
return $this->treeAge;
}
//设置苹果树的年龄
public function setTreeAge($age){
$this->treeAge = $age;
return true;
}
}
class grape implements fruit{
//葡萄是否有籽
private $seedLess;
public function grow(){
echo "apple grow";
}
public function plant(){
echo "apple plant";
}
public function harvest(){
echo "apple harvest";
}
public function eat(){
echo "apple eat";
}
//有无籽取值
public function getSeedLess(){
return $this->seedLess;
}
//设置有籽无籽
public function setSeedLess($seed){
$this->seedLess = $seed;
return true;
}
}
class farmer
{
//定义个静态工厂方法
public static function factory($fruitName){
switch ($fruitName) {
case 'apple':
return new apple();
break;
case 'grape':
return new grape();
break;
default:
throw new badFruitException("Error no the fruit", 1);
break;
}
}
}
class badFruitException extends Exception
{
public $msg;
public $errType;
public function __construct($msg = '' , $errType = 1){
$this->msg = $msg;
$this->errType = $errType;
}
}
/**
* 获取水果实例化的方法
*/
try{
$appleInstance = farmer::factory('apple');
var_dump($appleInstance);
}catch(badFruitException $err){
echo $err->msg . "_______" . $err->errType;
}
(六)原型模式(Prototype)
● 定义
相比正常创建一个对象 (new Foo () ),首先创建一个原型,然后克隆它会更节省开销。
● 代码示例 : 为每一本书设置标题
abstract class BookPrototype
{
/**
* @var string
*/
protected $title = 0;
/**
* @var string
*/
protected $category;
abstract public function __clone();
public function getTitle(): string
{
return $this->title;
}
public function setTitle($title)
{
$this->title = $title;
}
}
class BarBookPrototype extends BookPrototype
{
/**
* @var string
*/
protected $category = 'Bar';
public function __clone()
{
}
}
class FooBookPrototype extends BookPrototype
{
/**
* @var string
*/
protected $category = 'Foo';
public function __clone()
{
}
}
$fooPrototype = new FooBookPrototype();
$barPrototype = new BarBookPrototype();
for ($i = 5; $i < 10; $i++) {
$book = clone $fooPrototype;
$book->setTitle('Foo Book No ' . $i);
var_dump(new FooBookPrototype == $book);
}
for ($i = 0; $i < 5; $i++) {
$book = clone $barPrototype;
$book->setTitle('Bar Book No ' . $i);
var_dump(new BarBookPrototype == $book);
}
(七)对象池模式(Pool)
● 定义
对象池可以用于构造并且存放一系列的对象并在需要时获取调用。在初始化实例成本高,实例化率高,可用实例不足的情况下,对象池可以极大地提升性能。在创建对象(尤其是通过网络)时间花销不确定的情况下,通过对象池在短期时间内就可以获得所需的对象。
● 代码示例
class Factory {
protected static $products = array();
public static function pushProduct(Product $product) {
self::$products[$product->getId()] = $product;
}
public static function getProduct($id) {
return isset(self::$products[$id]) ? self::$products[$id] : null;
}
public static function removeProduct($id) {
if (array_key_exists($id, self::$products)) {
unset(self::$products[$id]);
}
}
}
Factory::pushProduct(new Product('first'));
Factory::pushProduct(new Product('second'));
print_r(Factory::getProduct('first')->getId());
// first
print_r(Factory::getProduct('second')->getId());
// second
(八)建造者模式(Builder)
● 定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
● 2)代码示例 建造相同标准的卡车和汽车。类似于变形金刚,相同的零件进行不同的组合.
● 分为 Director 导演者,负责构建、BuilderInterface 构建接口,规范建造标准、TruckBuilder 构建卡车类 CarBuilder 构建汽车类
Vehicle 零部件公共类、Truck Car Engine Wheel Door 零部件类、DirectorTest 测试类
class Director
{
public function build(BuilderInterface $builder): Vehicle
{
$builder->createVehicle();
$builder->addDoors();
$builder->addEngine();
$builder->addWheel();
return $builder->getVehicle();
}
}
interface BuilderInterface
{
public function createVehicle();
public function addWheel();
public function addEngine();
public function addDoors();
public function getVehicle(): Vehicle;
}
class TruckBuilder implements BuilderInterface
{
/**
* @var Truck
*/
private $truck;
public function addDoors()
{
$this->truck->setPart('rightDoor', new Door());
$this->truck->setPart('leftDoor', new Door());
}
public function addEngine()
{
$this->truck->setPart('truckEngine', new Engine());
}
public function addWheel()
{
$this->truck->setPart('wheel1', new Wheel());
$this->truck->setPart('wheel2', new Wheel());
$this->truck->setPart('wheel3', new Wheel());
$this->truck->setPart('wheel4', new Wheel());
$this->truck->setPart('wheel5', new Wheel());
$this->truck->setPart('wheel6', new Wheel());
}
public function createVehicle()
{
$this->truck = new Truck();
}
public function getVehicle(): Vehicle
{
return $this->truck;
}
}
class CarBuilder implements BuilderInterface
{
/**
* @var Car
*/
private $car;
public function addDoors()
{
$this->car->setPart('rightDoor', new Door());
$this->car->setPart('leftDoor', new Door());
$this->car->setPart('trunkLid', new Door());
}
public function addEngine()
{
$this->car->setPart('engine', new Engine());
}
public function addWheel()
{
$this->car->setPart('wheelLF', new Wheel());
$this->car->setPart('wheelRF', new Wheel());
$this->car->setPart('wheelLR', new Wheel());
$this->car->setPart('wheelRR', new Wheel());
}
public function createVehicle()
{
$this->car = new Car();
}
public function getVehicle(): Vehicle
{
return $this->car;
}
}
abstract class Vehicle
{
/**
* @var object[]
*/
private $data = [];
/**
* @param string $key
* @param object $value
*/
public function setPart($key, $value)
{
$this->data[$key] = $value;
}
}
class Truck extends Vehicle
{
}
class Car extends Vehicle
{
}
class Engine extends Vehicle
{
}
class Wheel extends Vehicle
{
}
class Door extends Vehicle
{
}
class DirectorTest
{
public function testCanBuildTruck()
{
$truckBuilder = new TruckBuilder();
return (new Director())->build($truckBuilder);
}
public function testCanBuildCar()
{
$carBuilder = new CarBuilder();
return (new Director())->build($carBuilder);
}
}
$directorTest = new DirectorTest();
var_dump($directorTest->testCanBuildTruck());
var_dump($directorTest->testCanBuildCar());
以上就是PHP设计模式的创建型的详细内容了,看完之后是否有所收获呢?如果想了解更多相关内容,欢迎关注亿速云行业资讯!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。