IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> PHP设计模式(2) -创建型模式 -> 正文阅读

[PHP知识库]PHP设计模式(2) -创建型模式

创建型模式主要是为了解决创建对象的时候的问题而存在的。

创建型设计模式有两个主导思想:一是将系统使用的具体类封装起来,二是隐藏这些具体类的实例创建和结合方式。

创建型模式主要分为以下五种:

  • 简单工厂模式(Simple Factory)和工厂方法模式(Factory method)
  • 抽象工厂模式(Abstract factory)
  • 单例模式(Singleton)
  • 建造者模式(Builder)
  • 原型模式(Prototype)

单例模式

单例模式的重点是,对象有且仅有一次实例化。
组成部分主要是:

  1. 私有化成员变量,存储实例化的对象
  2. 私有化构造方法,防止外部创建
  3. 私有化克隆方法,防止对象复制
  4. 公有的静态方法,对外界提供实例

上代码噻~

<?php
class Test{
    // 私有静态成员变量,保存全局实例
    private static $instance = NULL;
    // 私有构造方法,保证外界无法直接实例化
    private function __construct(){}
    // 防止克隆
    private function __clone(){}
    // 静态方法,返回此类唯一实例
    public static function getInstance(){
        if (!isset(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }
}

案例:
数据库连接

简单工厂模式

工厂模式:父类中提供一个创建对象的接口,用来允许子类决定实例化的类型

简单工厂模式:有抽象类,实现类,工厂类,把创建类这部分放在工厂类里面

<?php
    // 抽象类
    abstract class Math{
        abstract function getValue($x, $y){}
    }
    
    // 具体实现类
    class Add extends Math
     {
        public function getValue($x, $y) {
            return $x + $y;
        }
    }
    
    class Sub extends Math{
        public function getValue($x, $y) {
            return $x - $y;
        }
    }
    
    // 工厂类
    class MyMath{
        static function getClass($type) {
            switch ($type) {
                case "+":
                    return new Add();
                case "-":
                	return new Sub();
            }
        }
    }
    
    // 调用
    $myMath = MyMath::getClass("+");
    return $myMath->getValue(2, 3);
    

好处是调用简单, 创建对象和实例化分开,但是新增功能的时候需要修改工厂类,但是对其他部分代码不影响,定位问题也会更快。

工厂方法模式

封装类中不变的部分,提取善变的部分为独立类,通过依赖注入的方式达到解耦,复用和方便后期维护

  • 抽象工厂-------工艺的流程和顺序
  • 具体工厂-------隐藏背后产品的细节
  • 抽象产品-------产品生产工艺
  • 具体产品-------具体产品怎么生产,可以有个性化设置,只要工序按照抽象标准生产即可
<?php
    // 抽象类
    abstract class Math{
        abstract function getValue($x, $y){}
    }
    
    // 具体实现类1
    class Add extends Math
     {
        public function getValue($x, $y) {
            return $x + $y;
        }
    }
    
    // 具体实现类2
    class Sub extends Math{
        public function getValue($x, $y) {
            return $x - $y;
        }
    }
    
    // 抽象工厂类-和简单工厂方法最本质的区别就是创建对象的地方是抽出来的
    abstract class iFactory{
        abstract function getObj(){}
    }
    
    // 具体工厂类1
    class FactoryAdd extends iFactory{
        static function getObj(){
            return new Add();
        }
    }
    // 具体工厂类2
    class FactorySub extends iFactory{
        static function getObj(){
            return new Sub();
        }
    }
    // 具体调用。选择用哪个的过程交给客户端
    $client = FactoryAdd::getObj();
    return $client->getValue(2, 3);
    // 满足了开闭原则,但是可能会有很多类
    // 简单工厂更实用

应用例子:支付的话,支付宝支付,银行支付,微信支付。可以看作是一个典型的例子。
另一个例子就是PHP链接数据库的时候,不管是mysql还是sqlserver都抽象成同样的链接方式,查询方式,忽略底层不同的实现方式。

抽象工厂模式

产品类:

<?php

// 汽车(抽象产品接口)
interface AutoProduct
{
    public function dirve();
}

//奥迪A4(具体产品类)
class AudiA4Product implements AutoProduct
{
    //获取汽车名称
    public function dirve()
    {
        echo "开奥迪A4"."<br>";
    }
}

//奔驰C200(具体产品类)
class BenzC200Product implements AutoProduct
{
    //获取汽车名称
    public function dirve()
    {
        echo "开奔驰C200"."<br>";
    }
}


//空调(抽象产品接口)
interface AirCondition
{
    public function blow();
}

//格力空调某型号(具体产品类)
class GreeAirCondition implements AirCondition
{
    public function blow()
    {
        echo "吹格力空调某型号"."<br>";
    }
}

//海尔空调某型号(具体产品类)
class HaierAirCondition implements AirCondition
{
    public function blow()
    {
        echo "吹海尔空调某型号"."<br>";
    }
}


工厂类:
//工厂接口
interface Factory
{
    public function getAuto();
    public function getAirCondition();
}


//工厂A = 奥迪A4 + 海尔空调某型号
class AFactory implements Factory
{
    //汽车
    public function getAuto()
    {
        return new AudiA4Product();
    }

    //空调
    public function getAirCondition()
    {
        return new HaierAirCondition();
    }
}

//工厂B = 奔驰C200 + 格力空调某型号
class BFactory implements Factory
{
    //汽车
    public function getAuto()
    {
        return new BenzC200Product();
    }

    //空调
    public function getAirCondition()
    {
        return new GreeAirCondition();
    }
}


//客户端测试代码
$factoryA = new AFactory();
$factoryB = new BFactory();

//A工厂制作车
$auto_carA = $factoryA->getAuto();
$auto_airA = $factoryA->getAirCondition();

//B工厂制作车
$auto_carB = $factoryB->getAuto();
$auto_airB = $factoryB->getAirCondition();

//开奥迪车+吹海尔空调
$auto_carA->dirve();
$auto_airA->blow(); //热的时候可以吹吹空调

//开奔驰车+吹格力空调;
$auto_carB->dirve();
$auto_airB->blow(); //热的时候可以吹吹空调

?>

对比
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。

抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。

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

建造者模式

定义了处理其他对象的复杂构建的对象设计
将一个复杂对象的建造和调用者分离。调用者只需要给出指定对象的类型和那天。
建造者模式负责按照顺序创建复杂的对象/
组成部分:

建造请求(Builder):定义一个抽象接口,规范产品各个组成成分的建造,包括建造方法和返回结果的方法
具体建造者(Concrete Builder):实现builder定义的方法,建造结束之后返回一个产品实例
指挥者角色(Director):调用具体的建造者角色建造那个产品,
产品角色(Product):在指挥者的指导下由具体建造者建造的那个复杂的对象
优点:
易于解耦,建造者模式可以很好的将一个对象的实现和相关业务逻辑分离,将产品本身和创建过程分类,可以使用相同的过程来创建不同的产品。
易于精确的控制对象,将负责对象的创建划分在不同的方法中,过程更加清晰
易于扩展,增加新的建造者无需修改原来的类库
缺点:
建造者模式的产品有较多的共同点,组成部分类似,如果产品之间差异较大则不适合,如果产品的内部变化复杂,需要定义更多的具体建造者来配合,导致系统变得庞大
建造者接口修改会导致所有执行类的修改
使用场景:
需要生成的产品对象有复杂的内部结构,属性相互依赖,建造者模式可以强迫生成顺序
在对象创建过程中会使用到系统的一些其他对象,这些对象在产品创建过程中不易得到

<?php

    // 抽象接口,定义装配汽车的流水线
    abstract class Builder{
        // 造轮子
        public abstract function buildWheel(){}
        
        // 造椅子
        public abstract function buildChair(){}
        
       // 造发电机
       public abstract function buildEngine(){}
       
       // 组装完成
       public abstract function getCar(){}
    }
    
    // 指挥类,用于指挥具体建造者工作,厂长安排工人装配
    class Director{
        public function assemble(Builder $builder) {
            $builder->buildChair();
            $builder->buildWheel();
            $builder->buildEngine();
        }
    }
    
    // 具体产品类
    class Car{
        private $buildList = [];
        // 加零件
        public function add($part) {
            $this->buildList[] = $part;
        }
        
        // 展示零件
        public function show() {
            foreach ($this->buildList as $key => $builder) {
                echo '组件' . $builder . '安装好了</br>';
            }
            print_r('组装完毕');
        }
    }
    
    // 具体建造者一号,用于建造普通汽车
    class ConcreteBuilder extends Builder{
        private $car;
        
        public function __construct() {
            $this->car = new Car();
        }
        
        public function buildChair() {
            $this->car->add('装椅子');
        }
        
        public function buildWheel() {
            $this->car->add('装轮子');
        }
        
         public function buildEngine() {
            $this->car->add('装引擎');
        }
        
        public function getCar()
        {
            return $this->car;
        }
    }
    
    // 具体建造者二号,用于建造好汽车
     class ConcreteBuilder2 extends Builder{
        private $car;
        
        public function __construct() {
            $this->car = new Car();
        }
        
        public function buildChair() {
            $this->car->add('装好椅子');
        }
        
        public function buildWheel() {
            $this->car->add('装好轮子');
        }
        
         public function buildEngine() {
            $this->car->add('装好引擎');
        }
        
        public function getCar()
        {
            return $this->car;
        }
    }
    
    // 客户端
    // 指挥者
    $director = new Director();
    
   // 具体建造者1
   $builder = new ConcretrBuilder();
   $director->assemble($builder);
   $car = $builder->getCar();
   
   // 具体建造者2
   $builder2 = new ConcretrBuilder2();
   $director->assemble($builder2);
   $car2 = $builder2->getCar();

原型模式

通过创建一个原型对象,然后复制原型对象来避免通过标准的方式(这里说的是new)创建大量的对象产生的开销。

代码:

<?php

abstract class CloneMe
{
    public $name;
    public $picture;
    
    abstract function __clone();
}

class Person extends CloneMe
{
    public function __construct()
    {
        $this->picture = 'CloneMan.png';
        $this->name = 'Origin';
        
        public function display()
        {
            echo "<img src = $this->picture>";
            echo "<br/> $this->name<p/>";
        }
        
        function __clone(){
            
        }
    }
}

// 调用:只需要实例化一次
$worker = new Person();
$worker->display();

// 后续仅需要clone
$slacker = clone $worker;
$slacker->name = "Cloned";
$slacker->display();

有一个小的tips就是,克隆的时候并不会执行构造函数。

原型模式的优缺点
优点:
可以在运行时刻增加和删除产品
可以改变结构以指定新对象
可以改变值以指定新对象
减少子类的构造
用类动态配置应用
缺点:
每个类必须配一个克隆方法。
也就是说,当实例化的类是在运行时刻才知道的时候,比较适合原型模式。

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-08-27 11:38:35  更:2021-08-27 11:38:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/21 2:45:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码