大话PHP设计模式之创建型

<?php
/**
 * 单例模式(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()
    {
    }
}
?>

<?php 
/**
 * 多例模式(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 

?>

<?php
/**
 * 工厂方法模式(Factory Method)
 * 将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一个类。
 * 背景:小成有一间塑料加工厂(仅生产A类产品);随着客户需求的变化,客户需要生产B类产品;
 * 冲突:改变原有塑料加工厂的配置和变化非常困难,假设下一次客户需要再发生变化,再次改变将增大非常大的成本;
 * 解决方案:小成决定置办塑料分厂B来生产B类产品;
 * 原文链接:https://www.jb51.net/article/39037.htm
 */
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();
    }
}

?>

<?php
/**
 *抽象工厂模式(Abstract Factory)
 *有些情况下我们需要根据不同的选择逻辑提供不同的构造工厂,而对于多个工厂而言需要一个公共的抽象工厂标准
 *Product 定义抽象工厂标准
 *ShippableProduct 可运输产品 DigitalProduct 数码产品
 *ProductFactory 负责加载相对应产品
 *AbstractFactoryTest 测试类
 */
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);
    }
}

//测试类
class AbstractFactoryTest
{
    public function testCanCreateDigitalProduct(): bool
    {
        $factory = new ProductFactory();
        $product = $factory->createDigitalProduct(150);
        return new DigitalProduct(150) == $product;
    }
    public function testCanCreateShippableProduct(): bool
    {
        $factory = new ProductFactory();
        $product = $factory->createShippableProduct(150);
        return new ShippableProduct(150,50) == $product;
    }
    public function testCanCalculatePriceForDigitalProduct(): bool
    {
        $factory = new ProductFactory();
        $product = $factory->createDigitalProduct(150);
        return 150 == $product->calculatePrice();
    }
    public function testCanCalculatePriceForShippableProduct(): bool
    {
        $factory = new ProductFactory();
        $product = $factory->createShippableProduct(150);
        return 200 == $product->calculatePrice();
    }
}

$abFactoryTest = new AbstractFactoryTest();
var_dump($abFactoryTest->testCanCreateDigitalProduct());
var_dump($abFactoryTest->testCanCreateShippableProduct());
var_dump($abFactoryTest->testCanCalculatePriceForDigitalProduct());
var_dump($abFactoryTest->testCanCalculatePriceForShippableProduct());
/**
bool(true)
bool(true)
bool(true)
bool(true)
*/

?>

<?php

/**
 * 简单工厂模式(Simple Factory)
 * 简单工厂模式是一个精简版的工厂模式。
 * 它与静态工厂模式最大的区别是它不是『静态』的。因为非静态,所以你可以拥有多个不同参数的工厂,你可以为其创建子类
 * 工厂角色-具体产品-抽象产品
 * 一个事例
 * 一个农场,要向市场销售水果
 * 农场里有三种水果 苹果、葡萄
 * 我们设想:1、水果有多种属性,每个属性都有不同,但是,他们有共同的地方 |  生长、种植、收货、吃
 * 2、将来有可能会增加新的水果、我们需要定义一个接口来规范他们必须实现的方法
 * 3、我们需要获取某个水果的类,要从农场主那里去获取某个水果的实例,来知道如何生长、种植、收货、吃
 * 原文链接:https://www.cnblogs.com/aqsmoke/p/3955310.html
 */
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;
}

?>

<?php
/**
 * 原型模式(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);
}

?>

<?php
/**
 * 对象池模式(Pool)
 * 对象池可以用于构造并且存放一系列的对象并在需要时获取调用
 * 在初始化实例成本高,实例化率高,可用实例不足的情况下,对象池可以极大地提升性能。在创建对象(尤其是通过网络)时间花
 * 销不确定的情况下,通过对象池在可期时间内就可以获得所需的对象。
 * 转自:https://segmentfault.com/a/1190000003817321
 */
class Product {
 
    protected $id;
 
    public function __construct($id) {
        $this->id = $id;
    }
 
    public function getId() {
        return $this->id;
    }
}
 
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

?>

<?php
/**
 * 建造者模式(Builder)
 * Director 类是建造者模式的一部分。 它可以实现建造者模式的接口
 * 并在构建器的帮助下构建一个复杂的对象
 *
 * 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());

?>
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器学习模机器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值