从0开始学PHP面向对象内容之常用设计模式(享元)

二、结构型设计模式

7、享元模式(Flyweight Pattern)

这里是引用享元模式(Flyweight Pattern) 是一种结构型设计模式,旨在通过共享对象来减少内存使用,尤其适用于大量相似对象的场景。通过共享和重用对象的不可变部分(内部状态),从而减少重复对象的创建,节省内存。享元模式通过将对象的状态分为内部状态和外部状态,并共享内部状态,来优化内存使用。

享元模式的核心思想

享元模式的核心思想是共享对象,将多个对象的共同部分提取出来,避免内存中存在多个相同的实例对象。每个享元对象都包含
内部状态 :对象本身的状态,是可以共享的
外部状态:与对象行为相关的状态,每个对象实例可能是不同的,无法共享。通过这种方式,多个相同的对象可以共享相同的内部状态,儿不同的外部状态通过外部喜传入。

享元模式的结构

享元模式通常由以下几个组成部分构成

1、Flyweight(享元接口) :定义共享对象的接口,通常具有operation()方法,接受外部状态。

2、ConcreteFlyweight(具体享元) :实现享元接口的具体类,通常会存储共享内部状态。

3、FlyweightFactory(享元工厂) :负责创建和管理享元对象,确保对象的复用。当请求一个享元对象时,它会检查对象池中是否已有共享的对象,如果没有,就创建一个新的对象。

4、Client(客户端):负责给享元对象提供外部状态,并使用享元对象进行操作。

享元模式的工作流程

1、创建共享对象 :当客户端请求一个对象时,享元工厂会检查是否已有相同的对象。如果有,就返回已存在的对象;如果没有,则创建新的对象。

2、共享内部状态 :相同的享元对象共享内部状态,不同的对象实例通过外部状态来区分。

3、减少内存消耗:通过复用相同的对象,减少了不必要的对象创建,从而降低了内存消耗。

享元模式的代码实现

以下是一个使用享元模式的示例,假设我们有多个不同的字符对象,每个字符都有不同的外部状态(如位置、字体等),但字符的实际内容(如'A'、'B'等)是共享的内部状态。
1、定义享元接口和具体享元类

php 复制代码
// 享元接口
interface Flyweight {
    public function operation($extrinsicState);
}

// 具体享元类
class ConcreteFlyweight implements Flyweight {
    private $intrinsicState;

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

    public function operation($extrinsicState) {
        // 操作内部状态与外部状态
        return "IntrinsicState: " . $this->intrinsicState . ", ExtrinsicState: " . $extrinsicState;
    }
}

2、享元工厂类

享元工厂类负责管理享元对象池,确保共享的对象不会重复创建。

php 复制代码
在这里插入代码片class FlyweightFactory {
    private $flyweights = [];

    public function getFlyweight($key) {
        if (!isset($this->flyweights[$key])) {
            // 创建新的享元对象并缓存
            $this->flyweights[$key] = new ConcreteFlyweight($key);
        }
        return $this->flyweights[$key];
    }
}

3、客户端代码

客户端通过享元工厂获取共享对象,并传入外部状态来使用享元对象。

php 复制代码
// 客户端代码
$factory = new FlyweightFactory();

// 获取享元对象
$flyweight1 = $factory->getFlyweight("A");
$flyweight2 = $factory->getFlyweight("B");

// 使用享元对象
echo $flyweight1->operation("Position: (10, 20), Font: Arial") . PHP_EOL;  
// 输出: IntrinsicState: A, ExtrinsicState: Position: (10, 20), Font: Arial

echo $flyweight2->operation("Position: (30, 40), Font: Times New Roman") . PHP_EOL;
// 输出: IntrinsicState: B, ExtrinsicState: Position: (30, 40), Font: Times New Roman

享元模式的优缺点

优点:

1、节省内存 :通过共享对象,避免了重复创建相同的对象,从而节省内存。

2、提高性能 :减少了内存的使用和对象创建的开销,提高了系统的性能。

3、灵活性和扩展性:通过外部状态的传入,客户端可以在不改变内部状态的情况下,动态地改变对象的行为。

缺点:

1、增加复杂度 :需要将对象分为内部状态和外部状态,代码实现较为复杂。

2、难以管理 :享元工厂类需要管理共享对象池,随着对象数量的增多,管理起来可能变得比较复杂。

3、外部状态的管理:在享元模式中,外部状态是传递给对象的,这可能需要额外的管理逻辑来确保对象的一致性。

适用场景

1、内存消耗大的系统 :当需要创建大量相似对象时,使用享元模式可以显著减少内存使用。

2、对象状态可以分为内部和外部的情况 :当对象的内部状态是可以共享的,而外部状态是可变的时,享元模式非常适用。

3、对象数量庞大且有相似性的场景:如文本编辑器中的字符对象、图形绘制中的图形对象等。

实际应用

1、文本编辑器 :在文本编辑器中,字符是可以共享的,因为字符本身(如A、B)是固定的,然而每个字符的字体、大小、颜色等属性(外部状态)是不同的。

2、游戏开发:在大型多人在线游戏中,成千上万的玩家可能有相同的属性或行为,例如攻击动作、角色装备等,这些属性可以使用享元模式进行共享。

总结

关于设计模式中的结构型设计模式 告一段落了 ,下期开启设计模式中的行为型设计模式

相关推荐
JaguarJack6 小时前
FrankenPHP 原生支持 Windows 了
后端·php·服务端
BingoGo6 小时前
FrankenPHP 原生支持 Windows 了
后端·php
JaguarJack1 天前
PHP 的异步编程 该怎么选择
后端·php·服务端
BingoGo1 天前
PHP 的异步编程 该怎么选择
后端·php
JaguarJack2 天前
为什么 PHP 闭包要加 static?
后端·php·服务端
willow2 天前
Axios由浅入深
设计模式·axios
ServBay3 天前
垃圾堆里编码?真的不要怪 PHP 不行
后端·php
用户962377954483 天前
CTF 伪协议
php
七月丶4 天前
别再手动凑 PR 了:这个 AI Skill 会按仓库习惯自动建分支、拆提交、提 PR
人工智能·设计模式·程序员