PHP设计模式(十三)享元模式的实现

作者: 温新

分类: 【设计模式】

阅读: 2089

时间: 2020-04-19 05:16:33

一、什么是享元模式

**享元模式(Flyweight Pattern)**主要用于减少创建对象的数量,以减少内存占用和提高性能。

理解:

比如开发博客,小明需要新闻博客,小花需要图片博客......

这些博客都有一个释共同的特点:结构非常相似,如更换主题一样,

最先想到的可能是复制然后更改不同的文字,这是很繁琐的,

享元模式把可以共享的直接公共出来,不需要全部赋值,

直接更改不同的博客即可。

二、享元模式结构

抽象享元(Flyweight)角色:此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共介面。那些需要外蕴状态的操作可以通过呼叫商业以引数形式传入

具体享元(ConcreteFlyweight)角色:实现Flyweight介面,并为内部状态(如果有的话)拉回储存空间。ConcreteFlyweight物件必须是可共享的。它所储存的状态必须是内部的

不共享的具体享元(UnsharedConcreteFlyweight)角色:并非所有的Flyweight子类都需要被共享。Flyweigth使共享成为可能,但它并不强制共享。

享元工厂(FlyweightFactory)角色:负责建立和管理享元角色。本角色必须保证享元物件可能被系统适当地共享

三、享元模式使用场景

1、一个应用程式使用了大量的物件

2、完全由于使用大量的物件,造成很大的储存开销

3、物件的大多数状态都可变为外部状态

4、如果删除物件的外部状态,那么可以用相对较少的共享物件取代很多组物件

5、应用程式不依赖于物件标识。

四、享元模式优缺点

优点:可以大幅度地降低记忆体中物件的数量

缺点:

1、使得系统更加复杂

2、享元模式将享元物件的状态外部化,而读取外部状态使得执行时间稍微变长

五、代码实现

Blog.php 相当于Flyweight抽象角色

<?php

/**
 * 抽象Blog角色,相当于 Flyweight
 */
abstract class Blog
{
    // 私用博客名,禁止子类直接使用
    private $blogName;

    public function __construct(string $blogName)
    {
        $this->setWebsiteName($blogName);
    }

    public function setWebsiteName(string $blogName)
    {
        $this->blogName = $blogName;
    }

    public function getWebsiteName()
    {
        return $this->blogName;
    }
}

ConcreteBlog.php 相当于ConcreteFlyweight具体享元角色

<?php

/**
 * ConcreteBlog具体享元角色实现,相当于ConcreteFlyweight
 */
class ConcreteBlog extends Blog
{
    // 调用父类构造函数,初始化博客名
    public function __construct(string $blogName){
        parent::__construct($blogName);
    }

    public function show(User $user){
        echo '这是 ' . $user->getUserName() . ' 的网站 ' . $this->getWebsiteName() . '<hr>';

    }    
}

BlogFactory.php 相当于FlyweightFactory享元工厂角色

<?php

/**
 * BlogFactory享元工厂角色,FlyweightFactory
 */
class BlogFactory
{
    // 存储工厂实例对象
    private $blogs = [];

    /**
     * getBlog 生产对象
     *
     * @param int    $key  实例标识号
     * @param string $name 博客名
     * @return object
     */
    public function getBlog(int $key , string $name)
    {
        // 判断实例是否生产
        if(!isset($this->blogs[$key])){
            $this->blogs[$key] = new ConcreteBlog($name);
        }

        // 实例存在,返回实例对象
        return $this->blogs[$key];
    }
}

UnsharedBlog.php 相当于UnsharedConcreteFlyweight

<?php

class UnsharedBlog extends Blog
{
    // 调用父类构造函数,初始化博客名
    public function __construct(string $blogName){
        parent::__construct($blogName);
    }

    public function show(){
        echo '不共享的博客';
    }  
}

User.php

<?php

// 用户名
class User{
    private $name;

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

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

    public function getUserName(){
        return $this->name;
    }
}

index.php 客户端实现 <?php

include './Blog.php';
include './ConcreteBlog.php';
include './UnsharedBlog.php';
include './BlogFactory.php';
include './User.php';

class index
{
    public static function idx()
    {

        $flyweight = new BlogFactory();

        $website = $flyweight->getBlog(1,'blog');
        $website->show(new User('李四'));

        $wangwu = $flyweight->getBlog(1 , 'Liblog');
        $wangwu->show(new User('王五'));

        $zhaoliu = $flyweight->getBlog(2 , '论坛');
        $zhaoliu->show(new User('赵六'));

        // 简单实现不共享
        $unblog = new UnsharedBlog('不共享');
        $unblog->show();

    }
}
Index::idx();

我是夕阳何处寻,期待和优秀的你一起同行!

夕阳何处寻

2020年04月19日

请登录后再评论