简单工厂模式

简单工厂模式:叫静态工厂方法模式

无法灵活的拓展和维护,添加新的功能需要修改原有的代码
工厂类负责创建的对象较少,客户只知道传入工厂类的参数,对于如何创建对象不关心
并未严格遵循设计模式的开闭原则,当需要增加新产品时也需要修改工厂代码

<?php
class AppleDrink{
    function getDrinkName()
    {
        echo '苹果饮料';
    }

}

class BananaDrink{
    function getDrinkName()
    {
        echo '香蕉饮料';
    }

}

class FruitFactory{
    public static function makeDrink($fruit){
        if ($fruit == 'apple'){
            return new AppleDrink();
        }elseif ($fruit == 'banana'){
            return new BananaDrink();
        }
    }
}

$factory = new FruitFactory();
$apple = $factory->makeDrink('apple');
$apple->getDrinkName();
$banana = $factory->makeDrink('banana');
$banana->getDrinkName();
$apple1 = $factory->makeDrink('apple');
$apple1->getDrinkName();
$banana1 = $factory->makeDrink('banana');
$banana1->getDrinkName();

工厂方法模式

工厂模式,属于创建型模式,它提供了创建对象的最佳方式,在工厂模式中,我们创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

定义一个创建对象的接口,让子类自己决定去实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
工厂模式是一种类,它具有为您创建对象的某些方法,可以使用工厂类创建对象,而不直接使用new,如果需要更改所创建的对象类型,只需要修改工厂类即可。

<?php
interface Drink{
    function getDrinkName();
}

class AppleDrink implements Drink{
    function getDrinkName()
    {
        echo '苹果味饮料';
    }
}

class BananaDrink implements Drink{
    function getDrinkName()
    {
        echo '香蕉味饮料';
    }
}


interface FruitFactory{
    function makeDrink();
}

class AppleFactory implements FruitFactory{
    function makeDrink()
    {
        return new AppleDrink();
    }
}

class BananaFactory implements FruitFactory{
    function makeDrink()
    {
        return new BananaDrink();
    }
}

$appleFactory = new AppleFactory();
$apple = $appleFactory->makeDrink();
$apple->getDrinkName();

$bananaFactory = new BananaFactory();
$banana = $bananaFactory->makeDrink();
$banana->getDrinkName();

当需要增加新的产品时,只需要添加新的工厂类即可,不需要改动原来的代码。
工厂模式,它是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现开闭原则,实现了对扩展开放,对更改关闭。其次实现更复杂的层次结构,可以应用于产品结果复杂的场合。工厂方法模式是对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不在负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。

抽象工厂模式

抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。
所谓抽象工厂模式就是我们的抽象工厂约定了可以生产的产品,这些产品都包含多种规格,然后我们可以从抽象工厂为每一种规格派生出具体工厂类,然后让这些具体工厂类生产具体的产品。

抽象工厂模式包含如下角色:

AbstractFactory:抽象工厂
ConcreteFactory:具体工厂
AbstractProduct:抽象产品
Product:具体产品

<?php 
abstract class AbstractProductA                    //抽象产品类
{
    abstract public function use();
}

class ProductA1 extends AbstractProductA           //具体产品类
{
    public function use(){
        var_dump('productA1');
    }
}

abstract class AbstractFactory                     //抽象工厂类
{
    abstract public function createProductA();
}

class ConcreteFactory1 extends AbstractFactory     //具体工厂类
{
    public function createProductA()
    {
        return new ProductA1();
    }
}

$a=new ConcreteFactory1();
$b=$a->createProductA();
$b->use();         // 打印出string(9) "productA1"
?>

区别和适用范围

简单工厂模式、工厂方法模式、抽象工厂模式区别:
简单工厂模式:用来生产同一等级结构中的任意产品。对与增加新的产品,无能为力

工厂模式 :用来生产同一等级结构中的固定产品。(支持增加任意产品)
抽象工厂 :用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)

以上三种工厂 方法在等级结构和产品族这两个方向上的支持程度不同。所以要根据情况考虑应该使用哪种方法

适用范围
简单工厂模式:

工厂类负责创建的对象较少,客户只知道传入工厂类的参数,对于如何创建对象不关心。

工厂方法模式:

当一个类不知道它所必须创建对象的类或一个类希望由子类来指定它所创建的对象时,当类将创建对象的职责委托给多个帮助子类中得某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候,可以使用工厂方法模式。

抽象工厂模式:

一个系统不应当依赖于产品类实例何如被创建,组合和表达的细节,这对于所有形态的工厂模式都是重要的。这个系统有多于一个的产品族,而系统只消费其 中某一产品族。同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。系统提供一个产品类的库,所有的产品以同样的接口出现,从 而使客户端不依赖于实现。

策略模式

策略模式:定义一系列算法,将每个算法封装起来,并让它们可以互相替换,策略模式让算法的变化不会影响到使用它的客户。策略模式是一种对象行为型模式。

步骤组成:

  • 抽象策略角色:策略类,通常由一个接口抽或象类实现 具体策略角色:
  • 封装了相关算法和行为,具体实现父类的共同方法
  • 环境角色:接收保存实例,统一执行策略类接口方法

应用场景:

  • 多个类只区别在表现行为不同,在运行时动态选择具体要执行的行为
  • 对客户隐藏具体算法的实现细节,彼此完全独立
  • 需要在不同情况下使用不同算法

优点:

  • 策略模式提供了管理相关算法的办法,恰当使用继承可以把公共代码写入父类,避免重复代码
  • 每个算法都有自己单独的类,可以通过自己单独的接口进行测试,简化了单元测试。

缺点:

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类,因此,策略模式只适用于客户端知道所有算法或行为的情况下。
  • 策略模式会造成很多策略类,每个具体策略类会产生一个新类。

    <?php
    
    /**
     * Interface Travel 抽象策略角色
     * 约定具体方法
     */
    interface Travel
    {
        public function go();
    }
    
    /**
     * Class byBus具体策略角色
     * 乘公交
     */
    class byBus implements Travel {
        public function go()
        {
            echo '坐公交';
        }
    }
    

    /**

    • Class byMetro 具体策略角色
    • 乘地铁
      */

    class byMetro implements Travel
    {

    public function go()
    {
        echo '坐地铁';
    }

    }

    /**
     * Class byTrain 具体策略角色
     * 乘火车
     */
       class byTrain implements Travel
       {
            public function go()
            {
                echo '坐火车';
            }
        }
    
    /**
     * Class Main 环境角色
     */
    class Main{
        private $_strategy;
        private $_isChange = false;
    
    public function __construct(Travel $travel)
    {
        $this->_strategy = $travel;
    }
    
    /**
     * 改变出行方式
     *
     * @param Travel $travel
     */
    public function change(Travel $travel)
    {
        $this->_strategy = $travel;
        $this->_isChange = true;
    }
    
        public function goTravel()
        {
            $this->_strategy->go();
        }
    }
    
    /**
     * 客户端使用
     */
    $strategy = new Main(new byBus());
    // 乘公交
    $strategy->goTravel();
    // 乘地铁
    $strategy->change(new byMetro());
    $strategy->goTravel();
    // 自驾车
    $strategy->change(new byTrain());
    $strategy->goTravel();
    
    //运行结果:坐公交 坐地铁 坐火车
    

单例模式

单例模式是一种常用的软件设计模式,是属于创建型模式,其定义是单例对象的类只允许一个实例存在,即实例化出来的对象是唯一的。 特点:(三私一公)

  • 私有化一个属性用于存放唯一的实例
  • 私有化构造函数,防止被直接创建对象
  • 私有化克隆方法,防止克隆对象
  • 公有化静态方法,用于向系统提供这个实例

优点:

  • 使用单例模式可以避免大量的new操作,减少消耗资源。
  • 在内存里只有一个实例,减少内存的开心,尤其是频繁创建和销毁实例。
  • 避免对资源的多重占用,比如写文件操作。

缺点:

  • 不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态
  • 单例类的职责过重,在一定程度上违背了单一职责原则
  • 如果实例化的对象长时间不被利用,则会被系统回收,这将导致对象状态的丢失

    <?php 
    class Person{
    
    static private $instance;                 //创建静态私有的变量保存该类对象
    private $config;                          //参数
    private function __construct($config){    //防止外部代码使用new来创建对象。
        echo "我是";
        $this -> config = $config;
    }
    private function __clone(){               //防止克隆对象
    
    }
    static public function getInstance($config){
        if (!self::$instance instanceof self) {//判断$instance是否是Person的对象,没有则创建
            self::$instance = new self($config);
        }
        return self::$instance;
        
    }
    public function getName(){
        echo $this -> config;
    }
    }
    $db1 = Person::getInstance('Jack');
    $db1 -> getName();

    echo PHP_EOL;
    $db2 = Person::getInstance('John');
    $db2 -> getName();

    ?>

    //运行结果:
    我是Jack ($db1创建对象后,参数是jack)
    Jack($db2没有创建对象,而是直接使用$instance保存的唯一对象,所以输出的参数并没有变为John)

转载:PHP知识总结

最后修改:2021 年 03 月 29 日 04 : 09 PM
对您有帮助的话,请赏包辣条吧 ^~^