当前位置: 首页 > article >正文

从0开始学PHP面向对象内容之常用设计模式(建造者,原型)

在这里插入图片描述

一、创建型设计模式

3、建造者模式(Builder)

建造者模式(Builder Pattern)是一种创建型设计模式,他将一个复杂对象的构建过程与其表示分离,是的同样的构建过程可以创建不同的表示。
这种模式尤其适合创建复杂对象(包含多个组件),并且允许按照步骤逐步构建的对象

结构

1、Product(产品):要创建的复杂对象,由多个部件组成。
2、Builder(抽象建造者):定义创建产品步骤和接口
3、ConcreteBuilder(具体建造者):实现Builder接口,具体化构建的每一步,最终返回产品
4、Director(指挥官):控制建造过程,将复杂对象的构造步骤封装起来

场景说明
比如我们要生产一辆汽车,汽车的部分部件有车轮,引擎,车门等
那么汽车就是产品,
生产车轮等零件的工人是建造者,
分配具体的人员(部门)是具体建造者
决定是先造车轮还是造车门的人就是指挥者负责控制建造顺序
以下是代码实例

第一步:定义产品(Product)

class Car {
    public $wheels;
    public $engine;
    public $doors;

    public function showParts() {
        return "Car with {$this->wheels} wheels, {$this->engine} engine, {$this->doors} doors.";
    }
}

第二步:定义建造者接口(Builder)

interface CarBuilder {
    public function addWheels();
    public function addEngine();
    public function addDoors();
    public function getCar();
}

第三步:创建具体建造者(ConcreteBuilder)

class SportsCarBuilder implements CarBuilder {
    private $car;

    public function __construct() {
        $this->car = new Car();
    }

    public function addWheels() {
        $this->car->wheels = "4 sports wheels";
    }

    public function addEngine() {
        $this->car->engine = "V8 engine";
    }

    public function addDoors() {
        $this->car->doors = "2 doors";
    }

    public function getCar() {
        return $this->car;
    }
}

class SUVCarBuilder implements CarBuilder {
    private $car;

    public function __construct() {
        $this->car = new Car();
    }

    public function addWheels() {
        $this->car->wheels = "4 off-road wheels";
    }

    public function addEngine() {
        $this->car->engine = "V6 engine";
    }

    public function addDoors() {
        $this->car->doors = "4 doors";
    }

    public function getCar() {
        return $this->car;
    }
}

第四步:定义指挥者(Director)

class CarDirector {
    private $builder;

    public function __construct(CarBuilder $builder) {
        $this->builder = $builder;
    }

    public function buildCar() {
        $this->builder->addWheels();
        $this->builder->addEngine();
        $this->builder->addDoors();
        return $this->builder->getCar();
    }
}

下面我们就可以造车了

// 构建一辆跑车
$sportsCarBuilder = new SportsCarBuilder();
$director = new CarDirector($sportsCarBuilder);
$sportsCar = $director->buildCar();
echo $sportsCar->showParts(); // 输出:Car with 4 sports wheels, V8 engine, 2 doors.

// 构建一辆SUV
$suvCarBuilder = new SUVCarBuilder();
$director = new CarDirector($suvCarBuilder);
$suvCar = $director->buildCar();
echo $suvCar->showParts(); // 输出:Car with 4 off-road wheels, V6 engine, 4 doors.

是不是觉得上述有点冗长了?但是标准化的,对于简单的构建来说,我们可以使用建造者模式的变体:链式调用

示例

class SimpleCar {
    private $wheels;
    private $engine;
    private $doors;

    public function setWheels($wheels) {
        $this->wheels = $wheels;
        return $this;
    }

    public function setEngine($engine) {
        $this->engine = $engine;
        return $this;
    }

    public function setDoors($doors) {
        $this->doors = $doors;
        return $this;
    }

    public function showParts() {
        return "SimpleCar with {$this->wheels} wheels, {$this->engine} engine, {$this->doors} doors.";
    }
}

// 使用
$simpleCar = (new SimpleCar())
    ->setWheels('4 basic wheels')
    ->setEngine('Basic engine')
    ->setDoors('4 doors');

echo $simpleCar->showParts(); // 输出:SimpleCar with 4 basic wheels, Basic engine, 4 doors.

总结

建造者模式是一种非常灵活且结构化的模式,适合用于复杂对象的创建,尤其当对象包含多个部分且构造顺序很重要时。
通过将构造细节隐藏在 Builder 和 Director 内部,建造者模式为开发者提供了更高层次的代码抽象,极大地提升了代码的维护性和可扩展性。

优点:
1、清晰的构建过程:将复杂对象的创建步骤分开,逻辑清晰。
2、高度可扩展:可以通过添加新的具体建造者来构造不同的产品。
3、提高复用性:构建步骤可以被不同的建造者复用。
缺点:
增加了类的数量:每种具体产品需要对应一个具体建造者。
不适合简单对象:对于属性较少的对象,建造者模式显得多余。

但是我个人感觉它和工厂模式有点像,但是还是有区别的,具体的看下图,设计模式是死的,大家灵活运用
在这里插入图片描述
举个例子
1、如果需要创建的对象简单,且关注类型切换,选择工厂模式。比如生产不同类型的商品,创建数据库连接对象。
2、如果需要构造复杂对象,且关注步骤或构造细节,选择建造者模式。比如创建一辆汽车、一座房子,或生成复杂文档。
当然两者可以结合使用,比如工厂模式用于选择具体的建造者,建造者模式完成对象的详细构造过程。

4、原型模式(Prototype)

定义:

原型模式(Prototype Pattern) 是一种创建型设计模式,它允许通过复制现有对象来创建新对象,而不是重新实例化类。这种模式对创建成本高或初始化复杂的对象非常有用。

核心概念:

原型模式的目标:通过复制一个已有的对象(称为原型)来创建新对象,而无需了解创建的细节
原型模式的关键:使用现有对象作为蓝本,并对其进行克隆。

结构

1、 Prototype(原型接口):定义一个克隆方法,让对象能够复制自身。
2、 ConcretePrototype(具体原型类):实现克隆方法,返回自身的深拷贝浅拷贝
3、Client(客户端):通过调用克隆方法创建新对象,而不直接依赖构造函数。

深拷贝与浅拷贝的区别
在这里插入图片描述

浅拷贝:只复制对象本身,而不复制内部引用的对象。可以通过模式方法__clone实现
深拷贝:不仅复制对象本身,还递归复制内部引用的对象。通常需要手动实现深拷贝逻辑。

class PrototypeExample {
    public $value;

    public function __construct($value) {
        $this->value = $value;
    }

    public function __clone() {
        // 深拷贝逻辑
        $this->value = clone $this->value;
    }
}

$original = new PrototypeExample((object)["data" => 123]);
$shallowClone = clone $original; // 浅拷贝
$shallowClone->value->data = 456;

echo $original->value->data; // 输出 456(浅拷贝影响原对象)

// 深拷贝的场景可以通过自定义 __clone 实现

代码示例

第一步:定义抽象原型

abstract class Prototype {
    public $name;

    public function __construct($name) {
        $this->name = $name;
    }

    // 定义抽象克隆方法
    abstract public function __clone();
}

第二步:创建具体原型类

class ConcretePrototype extends Prototype {
    public $data;

    public function __construct($name, $data) {
        parent::__construct($name);
        $this->data = $data;
    }

    // 实现克隆方法
    public function __clone() {
        // 深拷贝或浅拷贝逻辑
        $this->data = clone $this->data;
    }
}

第三步:客户端

// 初始化一个具体原型对象
$original = new ConcretePrototype("Original Object", (object)["value" => 123]);

// 克隆对象
$cloned = clone $original;

// 修改克隆对象的属性
$cloned->name = "Cloned Object";
$cloned->data->value = 456;

// 输出
echo $original->name . " - " . $original->data->value . "\n"; // Original Object - 123
echo $cloned->name . " - " . $cloned->data->value . "\n";     // Cloned Object - 456

总结

原型模式的核心是通过复制现有对象快速创建新对象,而非重新实例化。

优点:
1、性能优化:复制现有对象比重新初始化更快,适合资源消耗大的对象创建场景。
2、简化对象创建:隐藏复杂的构造逻辑,客户端只需调用克隆方法。
3、动态对象创建:无需提前知道对象的具体类型,适合多变场景。
缺点:
1、实现复杂:深拷贝的实现可能较复杂,尤其是对象内部嵌套多层引用时。
2、内存管理问题:如果对象过大,频繁克隆会增加内存开销。
3、副作用风险:浅拷贝可能导致修改克隆对象时影响原对象。

所以适用场景:

1、对象创建成本高:例如数据库连接池、配置加载等场景。
2、需要创建对象的不同版本:例如游戏中的多个角色模板、文档生成等。
3、需要隐藏复杂的对象初始化过程。


http://www.kler.cn/a/401819.html

相关文章:

  • 优化装配,提升品质:虚拟装配在汽车制造中的关键作用
  • 【QT实战】加解密文件夹之————应用程序获取管理员权限
  • leetcode:344. 反转字符串(python3解法)
  • macbook外接2k/1080p显示器调试经验
  • 【Hadoop】【大数据技术基础】实践三 NoSQL数据库 大数据基础编程、实验和案例教程(第2版)
  • css浮动用法
  • 【PGCCC】PostgreSQL 数据库设计中的文本标识符 | 翻译
  • docker有哪些网络模式
  • 【计算机网络实验】之静态路由配置
  • 前端项目接入单元测试手册
  • 白蚁自动化监测系统的装置和优势
  • 【网络安全】(一) 0成本添加访问级监控
  • 【C/C++】随机数生成的现代化封装
  • 前端注册代码
  • C#获取视频第一帧_腾讯云媒体处理获取视频第一帧
  • C函数从lua中读取数据接口常用接口
  • kali搭建pikachu靶场
  • 论文翻译 | Learning to Transfer Prompts for Text Generation
  • 统信操作系统离线安装JDK、Nginx、elasticsearch、kibana、ik、pinyin
  • k8s篇之流量转发走向
  • 阿里云ACK容器如何配置pod分散在集群的不同节点上
  • Vue 3与TypeScript集成指南:构建类型安全的前端应用
  • 高阶C语言之五:(数据)文件
  • 【Java】ArrayList与LinkedList详解!!!
  • 一种由于吸入硅酸盐粉尘而引起的肺部疾病:pneumonoultramicroscopicsilicovolcanoconiosis
  • 【java-ffmpeg】java 内存测试和集成