以Kohana Cache设计为例

1、抽象类:E:\html\tproject\framework\modules\cache\classes\Cache.php

<?php defined('SYSPATH') or die('No direct script access.');

abstract class Cache extends Kohana_Cache {}

2、抽象类:E:\html\tproject\framework\modules\cache\classes\Kohana\Cache.php

<?php defined('SYSPATH') or die('No direct script access.');
/**
* Kohana Cache provides a common interface to a variety of caching engines. Tags are
* supported where available natively to the cache system. Kohana Cache supports multiple
* instances of cache engines through a grouped singleton pattern.
*
* ### Supported cache engines
*
* * [APC](http://php.net/manual/en/book.apc.php)
* * [eAccelerator](http://eaccelerator.net/)
* * File
* * [Memcache](http://memcached.org/)
* * [Memcached-tags](http://code.google.com/p/memcached-tags/)
* * [SQLite](http://www.sqlite.org/)
* * [Xcache](http://xcache.lighttpd.net/)
*
* ### Introduction to caching
*
* Caching should be implemented with consideration. Generally, caching the result of resources
* is faster than reprocessing them. Choosing what, how and when to cache is vital. PHP APC is
* presently one of the fastest caching systems available, closely followed by Memcache. SQLite
* and File caching are two of the slowest cache methods, however usually faster than reprocessing
* a complex set of instructions.
*
* Caching engines that use memory are considerably faster than the file based alternatives. But
* memory is limited whereas disk space is plentiful. If caching large datasets it is best to use
* file caching.
*
* ### Configuration settings
*
* Kohana Cache uses configuration groups to create cache instances. A configuration group can
* use any supported driver, with successive groups using the same driver type if required.
*
* #### Configuration example
*
* Below is an example of a _memcache_ server configuration.
*
* return array(
* 'memcache' => array( // Name of group
* 'driver' => 'memcache', // using Memcache driver
* 'servers' => array( // Available server definitions
* array(
* 'host' => 'localhost',
* 'port' => 11211,
* 'persistent' => FALSE
* )
* ),
* 'compression' => FALSE, // Use compression?
* ),
* )
*
* In cases where only one cache group is required, set `Cache::$default` (in your bootstrap,
* or by extending `Kohana_Cache` class) to the name of the group, and use:
*
* $cache = Cache::instance(); // instead of Cache::instance('memcache')
*
* It will return the cache instance of the group it has been set in `Cache::$default`.
*
* #### General cache group configuration settings
*
* Below are the settings available to all types of cache driver.
*
* Name | Required | Description
* -------------- | -------- | ---------------------------------------------------------------
* driver | __YES__ | (_string_) The driver type to use
*
* Details of the settings specific to each driver are available within the drivers documentation.
*
* ### System requirements
*
* * Kohana 3.0.x
* * PHP 5.2.4 or greater
*
* @package Kohana/Cache
* @category Base
* @version 2.0
* @author Kohana Team
* @copyright (c) 2009-2012 Kohana Team
* @license http://kohanaphp.com/license
*/
abstract class Kohana_Cache { const DEFAULT_EXPIRE = 3600; /**
* @var string default driver to use
*/
public static $default = 'file'; /**
* @var Kohana_Cache instances
*/
public static $instances = array(); /**
* Creates a singleton of a Kohana Cache group. If no group is supplied
* the __default__ cache group is used.
*
* // Create an instance of the default group
* $default_group = Cache::instance();
*
* // Create an instance of a group
* $foo_group = Cache::instance('foo');
*
* // Access an instantiated group directly
* $foo_group = Cache::$instances['default'];
*
* @param string $group the name of the cache group to use [Optional]
* @return Cache
* @throws Cache_Exception
*/
public static function instance($group = NULL)
{
// If there is no group supplied
if ($group === NULL)
{
// Use the default setting
$group = Cache::$default;
} if (isset(Cache::$instances[$group]))
{
// Return the current group if initiated already
return Cache::$instances[$group];
} $config = Kohana::$config->load('cache'); if ( ! $config->offsetExists($group))
{
throw new Cache_Exception(
'Failed to load Kohana Cache group: :group',
array(':group' => $group)
);
} $config = $config->get($group); // Create a new cache type instance
$cache_class = 'Cache_'.ucfirst($config['driver']);
Cache::$instances[$group] = new $cache_class($config); // Return the instance
return Cache::$instances[$group];
} /**
* @var Config
*/
protected $_config = array(); /**
* Ensures singleton pattern is observed, loads the default expiry
*
* @param array $config configuration
*/
protected function __construct(array $config)
{
$this->config($config);
} /**
* Getter and setter for the configuration. If no argument provided, the
* current configuration is returned. Otherwise the configuration is set
* to this class.
*
* // Overwrite all configuration
* $cache->config(array('driver' => 'memcache', '...'));
*
* // Set a new configuration setting
* $cache->config('servers', array(
* 'foo' => 'bar',
* '...'
* ));
*
* // Get a configuration setting
* $servers = $cache->config('servers);
*
* @param mixed key to set to array, either array or config path
* @param mixed value to associate with key
* @return mixed
*/
public function config($key = NULL, $value = NULL)
{
if ($key === NULL)
return $this->_config; if (is_array($key))
{
$this->_config = $key;
}
else
{
if ($value === NULL)
return Arr::get($this->_config, $key); $this->_config[$key] = $value;
} return $this;
} /**
* Overload the __clone() method to prevent cloning
*
* @return void
* @throws Cache_Exception
*/
final public function __clone()
{
throw new Cache_Exception('Cloning of Kohana_Cache objects is forbidden');
} /**
* Retrieve a cached value entry by id.
*
* // Retrieve cache entry from default group
* $data = Cache::instance()->get('foo');
*
* // Retrieve cache entry from default group and return 'bar' if miss
* $data = Cache::instance()->get('foo', 'bar');
*
* // Retrieve cache entry from memcache group
* $data = Cache::instance('memcache')->get('foo');
*
* @param string $id id of cache to entry
* @param string $default default value to return if cache miss
* @return mixed
* @throws Cache_Exception
*/
abstract public function get($id, $default = NULL); /**
* Set a value to cache with id and lifetime
*
* $data = 'bar';
*
* // Set 'bar' to 'foo' in default group, using default expiry
* Cache::instance()->set('foo', $data);
*
* // Set 'bar' to 'foo' in default group for 30 seconds
* Cache::instance()->set('foo', $data, 30);
*
* // Set 'bar' to 'foo' in memcache group for 10 minutes
* if (Cache::instance('memcache')->set('foo', $data, 600))
* {
* // Cache was set successfully
* return
* }
*
* @param string $id id of cache entry
* @param string $data data to set to cache
* @param integer $lifetime lifetime in seconds
* @return boolean
*/
abstract public function set($id, $data, $lifetime = 3600); /**
* Delete a cache entry based on id
*
* // Delete 'foo' entry from the default group
* Cache::instance()->delete('foo');
*
* // Delete 'foo' entry from the memcache group
* Cache::instance('memcache')->delete('foo')
*
* @param string $id id to remove from cache
* @return boolean
*/
abstract public function delete($id); /**
* Delete all cache entries.
*
* Beware of using this method when
* using shared memory cache systems, as it will wipe every
* entry within the system for all clients.
*
* // Delete all cache entries in the default group
* Cache::instance()->delete_all();
*
* // Delete all cache entries in the memcache group
* Cache::instance('memcache')->delete_all();
*
* @return boolean
*/
abstract public function delete_all(); /**
* Replaces troublesome characters with underscores.
*
* // Sanitize a cache id
* $id = $this->_sanitize_id($id);
*
* @param string $id id of cache to sanitize
* @return string
*/
protected function _sanitize_id($id)
{
// Change slashes and spaces to underscores
return str_replace(array('/', '\\', ' '), '_', $id);
}
}
// End Kohana_Cache

 

3、缓存方式File、Memcache、Apc、Wincache实现类

3.1、E:\html\tproject\framework\modules\cache\classes\Cache\File.php

<?php defined('SYSPATH') or die('No direct script access.');

class Cache_File extends Kohana_Cache_File {}

3.2、E:\html\tproject\framework\modules\cache\classes\Kohana\Cache\File.php

<?php defined('SYSPATH') or die('No direct script access.');
/**
* [Kohana Cache](api/Kohana_Cache) File driver. Provides a file based
* driver for the Kohana Cache library. This is one of the slowest
* caching methods.
*
* ### Configuration example
*
* Below is an example of a _file_ server configuration.
*
* return array(
* 'file' => array( // File driver group
* 'driver' => 'file', // using File driver
* 'cache_dir' => APPPATH.'cache/.kohana_cache', // Cache location
* ),
* )
*
* In cases where only one cache group is required, if the group is named `default` there is
* no need to pass the group name when instantiating a cache instance.
*
* #### General cache group configuration settings
*
* Below are the settings available to all types of cache driver.
*
* Name | Required | Description
* -------------- | -------- | ---------------------------------------------------------------
* driver | __YES__ | (_string_) The driver type to use
* cache_dir | __NO__ | (_string_) The cache directory to use for this cache instance
*
* ### System requirements
*
* * Kohana 3.0.x
* * PHP 5.2.4 or greater
*
* @package Kohana/Cache
* @category Base
* @author Kohana Team
* @copyright (c) 2009-2012 Kohana Team
* @license http://kohanaphp.com/license
*/
class Kohana_Cache_File extends Cache implements Cache_GarbageCollect { /**
* Creates a hashed filename based on the string. This is used
* to create shorter unique IDs for each cache filename.
*
* // Create the cache filename
* $filename = Cache_File::filename($this->_sanitize_id($id));
*
* @param string $string string to hash into filename
* @return string
*/
protected static function filename($string)
{
return sha1($string).'.cache';
} /**
* @var string the caching directory
*/
protected $_cache_dir; /**
* Constructs the file cache driver. This method cannot be invoked externally. The file cache driver must
* be instantiated using the `Cache::instance()` method.
*
* @param array $config config
* @throws Cache_Exception
*/
protected function __construct(array $config)
{
// Setup parent
parent::__construct($config); try
{
$directory = Arr::get($this->_config, 'cache_dir', Kohana::$cache_dir);
$this->_cache_dir = new SplFileInfo($directory);
}
// PHP < 5.3 exception handle
catch (ErrorException $e)
{
$this->_cache_dir = $this->_make_directory($directory, 0777, TRUE);
}
// PHP >= 5.3 exception handle
catch (UnexpectedValueException $e)
{
$this->_cache_dir = $this->_make_directory($directory, 0777, TRUE);
} // If the defined directory is a file, get outta here
if ($this->_cache_dir->isFile())
{
throw new Cache_Exception('Unable to create cache directory as a file already exists : :resource', array(':resource' => $this->_cache_dir->getRealPath()));
} // Check the read status of the directory
if ( ! $this->_cache_dir->isReadable())
{
throw new Cache_Exception('Unable to read from the cache directory :resource', array(':resource' => $this->_cache_dir->getRealPath()));
} // Check the write status of the directory
if ( ! $this->_cache_dir->isWritable())
{
throw new Cache_Exception('Unable to write to the cache directory :resource', array(':resource' => $this->_cache_dir->getRealPath()));
}
} /**
* Retrieve a cached value entry by id.
*
* // Retrieve cache entry from file group
* $data = Cache::instance('file')->get('foo');
*
* // Retrieve cache entry from file group and return 'bar' if miss
* $data = Cache::instance('file')->get('foo', 'bar');
*
* @param string $id id of cache to entry
* @param string $default default value to return if cache miss
* @return mixed
* @throws Cache_Exception
*/
public function get($id, $default = NULL)
{
$filename = Cache_File::filename($this->_sanitize_id($id));
$directory = $this->_resolve_directory($filename); // Wrap operations in try/catch to handle notices
try
{
// Open file
$file = new SplFileInfo($directory.$filename); // If file does not exist
if ( ! $file->isFile())
{
// Return default value
return $default;
}
else
{
// Test the expiry
if ($this->_is_expired($file))
{
// Delete the file
$this->_delete_file($file, FALSE, TRUE);
return $default;
} // open the file to read data
$data = $file->openFile(); // Run first fgets(). Cache data starts from the second line
// as the first contains the lifetime timestamp
$data->fgets(); $cache = ''; while ($data->eof() === FALSE)
{
$cache .= $data->fgets();
} return unserialize($cache);
} }
catch (ErrorException $e)
{
// Handle ErrorException caused by failed unserialization
if ($e->getCode() === E_NOTICE)
{
throw new Cache_Exception(__METHOD__.' failed to unserialize cached object with message : '.$e->getMessage());
} // Otherwise throw the exception
throw $e;
}
} /**
* Set a value to cache with id and lifetime
*
* $data = 'bar';
*
* // Set 'bar' to 'foo' in file group, using default expiry
* Cache::instance('file')->set('foo', $data);
*
* // Set 'bar' to 'foo' in file group for 30 seconds
* Cache::instance('file')->set('foo', $data, 30);
*
* @param string $id id of cache entry
* @param string $data data to set to cache
* @param integer $lifetime lifetime in seconds
* @return boolean
*/
public function set($id, $data, $lifetime = NULL)
{
$filename = Cache_File::filename($this->_sanitize_id($id));
$directory = $this->_resolve_directory($filename); // If lifetime is NULL
if ($lifetime === NULL)
{
// Set to the default expiry
$lifetime = Arr::get($this->_config, 'default_expire', Cache::DEFAULT_EXPIRE);
} // Open directory
$dir = new SplFileInfo($directory); // If the directory path is not a directory
if ( ! $dir->isDir())
{
$this->_make_directory($directory, 0777, TRUE);
} // Open file to inspect
$resouce = new SplFileInfo($directory.$filename);
$file = $resouce->openFile('w'); try
{
$data = $lifetime."\n".serialize($data);
$file->fwrite($data, strlen($data));
return (bool) $file->fflush();
}
catch (ErrorException $e)
{
// If serialize through an error exception
if ($e->getCode() === E_NOTICE)
{
// Throw a caching error
throw new Cache_Exception(__METHOD__.' failed to serialize data for caching with message : '.$e->getMessage());
} // Else rethrow the error exception
throw $e;
}
} /**
* Delete a cache entry based on id
*
* // Delete 'foo' entry from the file group
* Cache::instance('file')->delete('foo');
*
* @param string $id id to remove from cache
* @return boolean
*/
public function delete($id)
{
$filename = Cache_File::filename($this->_sanitize_id($id));
$directory = $this->_resolve_directory($filename); return $this->_delete_file(new SplFileInfo($directory.$filename), FALSE, TRUE);
} /**
* Delete all cache entries.
*
* Beware of using this method when
* using shared memory cache systems, as it will wipe every
* entry within the system for all clients.
*
* // Delete all cache entries in the file group
* Cache::instance('file')->delete_all();
*
* @return boolean
*/
public function delete_all()
{
return $this->_delete_file($this->_cache_dir, TRUE);
} /**
* Garbage collection method that cleans any expired
* cache entries from the cache.
*
* @return void
*/
public function garbage_collect()
{
$this->_delete_file($this->_cache_dir, TRUE, FALSE, TRUE);
return;
} /**
* Deletes files recursively and returns FALSE on any errors
*
* // Delete a file or folder whilst retaining parent directory and ignore all errors
* $this->_delete_file($folder, TRUE, TRUE);
*
* @param SplFileInfo $file file
* @param boolean $retain_parent_directory retain the parent directory
* @param boolean $ignore_errors ignore_errors to prevent all exceptions interrupting exec
* @param boolean $only_expired only expired files
* @return boolean
* @throws Cache_Exception
*/
protected function _delete_file(SplFileInfo $file, $retain_parent_directory = FALSE, $ignore_errors = FALSE, $only_expired = FALSE)
{
// Allow graceful error handling
try
{
// If is file
if ($file->isFile())
{
try
{
// Handle ignore files
if (in_array($file->getFilename(), $this->config('ignore_on_delete')))
{
$delete = FALSE;
}
// If only expired is not set
elseif ($only_expired === FALSE)
{
// We want to delete the file
$delete = TRUE;
}
// Otherwise...
else
{
// Assess the file expiry to flag it for deletion
$delete = $this->_is_expired($file);
} // If the delete flag is set delete file
if ($delete === TRUE)
return unlink($file->getRealPath());
else
return FALSE;
}
catch (ErrorException $e)
{
// Catch any delete file warnings
if ($e->getCode() === E_WARNING)
{
throw new Cache_Exception(__METHOD__.' failed to delete file : :file', array(':file' => $file->getRealPath()));
}
}
}
// Else, is directory
elseif ($file->isDir())
{
// Create new DirectoryIterator
$files = new DirectoryIterator($file->getPathname()); // Iterate over each entry
while ($files->valid())
{
// Extract the entry name
$name = $files->getFilename(); // If the name is not a dot
if ($name != '.' AND $name != '..')
{
// Create new file resource
$fp = new SplFileInfo($files->getRealPath());
// Delete the file
$this->_delete_file($fp, $retain_parent_directory, $ignore_errors, $only_expired);
} // Move the file pointer on
$files->next();
} // If set to retain parent directory, return now
if ($retain_parent_directory)
{
return TRUE;
} try
{
// Remove the files iterator
// (fixes Windows PHP which has permission issues with open iterators)
unset($files); // Try to remove the parent directory
return rmdir($file->getRealPath());
}
catch (ErrorException $e)
{
// Catch any delete directory warnings
if ($e->getCode() === E_WARNING)
{
throw new Cache_Exception(__METHOD__.' failed to delete directory : :directory', array(':directory' => $file->getRealPath()));
}
throw $e;
}
}
else
{
// We get here if a file has already been deleted
return FALSE;
}
}
// Catch all exceptions
catch (Exception $e)
{
// If ignore_errors is on
if ($ignore_errors === TRUE)
{
// Return
return FALSE;
}
// Throw exception
throw $e;
}
} /**
* Resolves the cache directory real path from the filename
*
* // Get the realpath of the cache folder
* $realpath = $this->_resolve_directory($filename);
*
* @param string $filename filename to resolve
* @return string
*/
protected function _resolve_directory($filename)
{
return $this->_cache_dir->getRealPath().DIRECTORY_SEPARATOR.$filename[0].$filename[1].DIRECTORY_SEPARATOR;
} /**
* Makes the cache directory if it doesn't exist. Simply a wrapper for
* `mkdir` to ensure DRY principles
*
* @link http://php.net/manual/en/function.mkdir.php
* @param string $directory directory path
* @param integer $mode chmod mode
* @param boolean $recursive allows nested directories creation
* @param resource $context a stream context
* @return SplFileInfo
* @throws Cache_Exception
*/
protected function _make_directory($directory, $mode = 0777, $recursive = FALSE, $context = NULL)
{
// call mkdir according to the availability of a passed $context param
$mkdir_result = $context ?
mkdir($directory, $mode, $recursive, $context) :
mkdir($directory, $mode, $recursive); // throw an exception if unsuccessful
if ( ! $mkdir_result)
{
throw new Cache_Exception('Failed to create the defined cache directory : :directory', array(':directory' => $directory));
} // chmod to solve potential umask issues
chmod($directory, $mode); return new SplFileInfo($directory);
} /**
* Test if cache file is expired
*
* @param SplFileInfo $file the cache file
* @return boolean TRUE if expired false otherwise
*/
protected function _is_expired(SplFileInfo $file)
{
// Open the file and parse data
$created = $file->getMTime();
$data = $file->openFile("r");
$lifetime = (int) $data->fgets(); // If we're at the EOF at this point, corrupted!
if ($data->eof())
{
throw new Cache_Exception(__METHOD__ . ' corrupted cache file!');
} //close file
$data = null; // test for expiry and return
return (($lifetime !== 0) AND ( ($created + $lifetime) < time()));
}
}

  

4、使用

$key = 'AjSR/piQT24JaYEgh6V9tA==';
$data = array('id'=>1, 'name'=>'liuchao');
Cache::instance("file")->set($key, $data, 60);

  

php 抽象类适配器设计模式的更多相关文章

  1. Java适配器设计模式

    适配器设计模式,一个接口首先被一个抽象类先实现(此抽象类通常称为适配器类),并在此抽象类中实现若干方法(但是这个抽象类中的方法体是空的),则以后的子类直接继承此抽象类,就可以有选择地覆写所需要的方法. ...

  2. [gkk]传智-适配器设计模式,如同电源适配器

    //适配器设计模式 是图形化设计中用的.如同电源适配器 import java.awt.*; inport java.awte public calss MyFrame{ public static ...

  3. JAVA基础—适配器设计模式

    适配器概念 在计算机编程中,适配器模式将一个类的接口适配成用户所期待的.使用适配器,可以使接口不兼容而无法在一起工作的类协调工作,做法是将类自己包裹在一个已经存在的类中. JDK对适配器设计模式的应用 ...

  4. Java设计模式之适配器设计模式(项目升级案例)

    今天是我学习到Java设计模式中的第三个设计模式了,但是天气又开始变得狂热起来,对于我这个凉爽惯了的青藏人来说,又是非常闹心的一件事儿,好了不管怎么样,目标还是目标(争取把23种Java设计模式接触一 ...

  5. IOS设计模式第六篇之适配器设计模式

    版权声明:原创作品,谢绝转载!否则将追究法律责任. 那么怎么使用适配器设计模式呢? 这个之前提到的水平滚动的视图像这样: 为了开始实现他,我们创建一个新的继承与UIView的HorizontalScr ...

  6. 适配器设计模式初探(Java实现)

    本篇随笔主要介绍Java实现设配器设计模式. 先来看下待解决的问题: (图片转自http://blog.csdn.net/jason0539) 由上图的情况可知,欧洲壁式插座只有三足插口,如果我们想要 ...

  7. Design Pattern Adaptor 适配器设计模式

    适配器设计模式是为了要使用一个旧的接口,或许这个接口非常难用,或许是和新的更新的接口不兼容,所以须要设计一个适配器类,然后就能够让新旧的接口都统一. 就是这种一个图: watermark/2/text ...

  8. 适配器设计模式及GenericServlet(九)

    一共两个知识点:1.Servlet 里面已经有适配器了,名字叫:GenericServlet.      2.什么是适配器模式. 如果这个接口里面有好多方法,那创建A/B/C这个三个类的时候如果必须继 ...

  9. php适配器设计模式

    <?php //适配器模式 //服务器端代码 class tianqi{ public static function show(){ $today= array('tep' =>28 , ...

随机推荐

  1. python控制流-名词解释

    一.控制流的元素 控制流语句的开始部分通常是“条件”,接下来是一个代码块,称为“子句”. 二.控制流的条件 条件为了判断下一步如何进行,从而求布尔值的表达式.几乎所有的控制流语句都使用条件. 三.代码 ...

  2. 1~n的全排列--阅文集团2018校招笔试题

    题目大意:给定整数n,求出1~n的全排列 示例 输入:n=3 输出:[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1] import java.util.S ...

  3. DockerFile与镜像(Image)仓库

    深入Docker 之 Image: 当我们使用docker pull mysql 这个命令获取镜像的时候,到底他是怎么做的?我们登录官方提供的仓库看一下 https://github.com/dock ...

  4. 【转】mysqldump原理探究

    作者:胡儿胡儿 来源:CSDN 原文:https://blog.csdn.net/cug_jiang126com/article/details/49824471 —————————————————— ...

  5. 解决org.apache.subversion.javahl.ClientException的方法【】

    重新刷新项目,配置项目,总是报“The project was not built due to "org.apache.subversion.javahl.ClientException” ...

  6. 使用批处理命令注册运行mysql数据库,无需注册mysql服务,可以在任意电脑登录使用

    使用批处理命令初始化和开启mysql服务,移植数据库之后可以直接运行访问,对于学习数据库的人来说特别的方便哦. 我们可以从mysql官网下载官方社区版本的mysql: 这里使用之前下载的8.0.15来 ...

  7. C++ cin相关函数总结

    输入原理: 程序的输入都建有一个缓冲区,即输入缓冲区.一次输入过程是这样的,当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin函数直接从输入缓冲区中取数据.正因为cin函数是直接从缓冲区取数据 ...

  8. antd组件Upload实现自己上传

    前言 在实现图片上传时,可能需要用到Upload,但是它默认的上传方式是加入图片后直接上传,如果要实现最后再一次性上传,需要自定义内容. //添加按钮的样式 const uploadButton = ...

  9. 03.AutoMapper 之反向映射与逆向扁平化(Reverse Mapping and Unflattening)

    https://www.jianshu.com/p/d72400b337e0 AutoMapper现在支持更丰富的反向映射支持. 假设有以下实体: public class Order { publi ...

  10. GitHub入门使用

    1.首先注册账号. 2.新建仓库. 3.安装GitBash 4.首先要在本地创建一个ssh key. $ ssh -keygen -t rsa -C "your email@.com&quo ...