设计模式 享元模式

124 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。 image.png

介绍

shiyanlou:享元模式(英语:Flyweight Pattern)是一种软件设计模式。它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,它是一种对象结构型模式。享元模式的核心在于享元工厂类,享元工厂类的作用在于提供一个用于存储享元对象的享元池,用户需要对象时,首先从享元池中获取,如果享元池中不存在,则创建一个新的享元对象返回给用户,并在享元池中保存该新增对象。

角色

角色说明
Flyweight抽象享元类
ConcreteFlyweight具体享元类
UnsharedConcreteFlyweight非共享具体享元类
FlyweightFactory享元工厂类

角色示例

类名担任角色说明
SongFlyweight歌曲
FreeSongConcreteFlyweight免费歌曲
VipSongUnsharedConcreteFlyweightVip 歌曲
QQMusicFlyweightFactoryQQMusic 播放器

UML类图

image.png

代码

<?php
interface Song{
    public function play();
    public function download();
}

class FreeSong implements Song
{
    public $name;
    function __construct($name=null)
    {
        $this->name = $name;
    }

    public function play()
    {
        return '播放《'.$this->name.'》'.PHP_EOL;
    }

    public function download()
    {
        return '下载《'.$this->name.'》'.PHP_EOL;
    }
}

class VipSong implements Song
{
    public $name;
    function __construct($name=null)
    {
        $this->name = $name;
    }

    public function play()
    {
        return '不是VIP,不能播放《'.$this->name.'》'.PHP_EOL;
    }

    public function download()
    {
        return '不是VIP,不能下载《'.$this->name.'》'.PHP_EOL;
    }
}

class QQMusic
{
    public $song;
    protected static $myPlaylist;
    function __construct($song)
    {
        $this->song = $song;
        if (!isset(self::$myPlaylist)) {
            self::$myPlaylist = [];
        }
    }

    public function addMyPlaylist($name)
    {
        if (!array_key_exists($name,self::$myPlaylist)) {
            self::$myPlaylist[$name] = $this->song->name = $name;
            return '《'.$name.'》已添加到我的歌单'.PHP_EOL;
        } else {
            return '《'.$name.'》已存在于我的歌单'.PHP_EOL;
        }
    }
}

$freeSong = new FreeSong();
$qqMusic = new QQMusic($freeSong);
echo $qqMusic->addMyPlaylist('Faded');
echo $qqMusic->song->download();
echo $qqMusic->song->play();

echo $qqMusic->addMyPlaylist('Different World');
echo $qqMusic->song->download();
echo $qqMusic->song->play();

echo $qqMusic->addMyPlaylist('Faded');
echo $qqMusic->song->download();
echo $qqMusic->song->play();

$vipSong = new VipSong();
$qqMusic = new QQMusic($vipSong);
echo $qqMusic->addMyPlaylist('Lost Control');
echo $qqMusic->song->download();
echo $qqMusic->song->play();

echo $qqMusic->addMyPlaylist('Lily');
echo $qqMusic->song->download();
echo $qqMusic->song->play();

echo $qqMusic->addMyPlaylist('Lily');
echo $qqMusic->song->download();
echo $qqMusic->song->play();

创建 Test.php,内容如上。

执行

$ php Test.php
《Faded》已添加到我的歌单
下载《Faded》
播放《Faded》
《Different World》已添加到我的歌单
下载《Different World》
播放《Different World》
《Faded》已存在于我的歌单
下载《Different World》
播放《Different World》
《Lost Control》已添加到我的歌单
不是VIP,不能下载《Lost Control》
不是VIP,不能播放《Lost Control》
《Lily》已添加到我的歌单
不是VIP,不能下载《Lily》
不是VIP,不能播放《Lily》
《Lily》已存在于我的歌单
不是VIP,不能下载《Lily》
不是VIP,不能播放《Lily