1.单例模式
单例模式.pngclass Preferences{
private $props = array();
private static $instance;
//设置为私有不能在外部初始化
private function __construct()
{
}
public function getProperty($key) {
return $this->props[$key];
}
public function setProperty($key,$val){
$this->props[$key] = $val;
}
public static function getInstance()
{
// if (empty(static::$instance)){
// static::$instance = new Preferences();
// }
// return static::$instance;
//这样写代码会进行类型提示,编译器会自动推断类型
if (!self::$instance instanceof self) {
self::$instance = new self();
}
return self::$instance;
}
//防止clone,设置为私有
private function __clone()
{
}
}
$instance = Preferences::getInstance();
$instance->setProperty('a','1');
$instance->setProperty('b','2');
unset($instance);//下面的值依旧可以用
$instance2 = Preferences::getInstance();
echo $instance2->getProperty('a');
echo $instance2->getProperty('b');
单例模式保证任何时刻都只有一份实例,可以用来对全局设置一些配置,也可以在需要用到全局变量的地方写到单例里面,方便管理。
2.工厂方法模式
一个关于个人事务管理的项目,要求管理预约对象,业务团队和另一个公司建立关系,需要用一个叫做BloggsCal的格式和他们团队交流预约的相关数据,以后还可能有其他的数据格式。
image.pngabstract class ApptEncode
{
abstract function encode();
}
//Bloggs编码格式
class BloggsApptEncoder extends ApptEncode
{
function encode()
{
echo ' appointment -- bloggs';
}
}
//Mega编码格式
class MegaApptEncoder extends ApptEncode
{
function encode()
{
echo ' appointment -- Mega';
}
}
//根据不同的场景获取编码器类,调用相关的编码器生成数据,可以根据传递的参数类型生成
class CommsManager
{
const BLLOGS = 1;
const MEGA =2;
private $mode;
public function __construct($mode)
{
$this->mode = $mode;
}
public function getEncoder()
{
switch ($this->mode) {
case (self::BLLOGS):
return new BloggsApptEncoder();
default:
return new MegaApptEncoder();
}
}
//页眉输出
public function getHeads() {
switch ($this->mode) {
case (self::BLLOGS):
return "bllggs header";
default:
return "mega header";
}
}
}
通过标志位加switch判断可以在getEncoder方法里面实例化需要的对象,但是如果需要额外的操作,比如增加页眉,switch语句会遍布整个类,多态的使用可以避免if或者switch判断。
把管理类改成下面的形式就是工厂方法模式,工厂方法模式会导致特殊代码重复,不能为创建者创建子类就只是为了实现工厂方法模式,如果没有页眉也页脚这样的话,完全可以用改进前的形式。
工厂方法模式把创建者类与要生产的产品类分离开来,创建者是一个工厂类,其中定义了用于生产产品对象的类方法。如果没有提供默认实现就要创建者类的子类来实例化,一般情况下一个创建者的子类对应一个产品。
abstract class CommsManager
{
abstract public function getHead();
abstract public function getFooter();
abstract public function getEncoder();
}
class BloggsCommsManager extends CommsManager
{
public function getEncoder()
{
return new BloggsApptEncoder();
}
public function getFooter()
{
return "Bloggs -- footer ";
}
public function getHead()
{
return "Bloggs -- header ";
}
}
class MegaCommsManager extends CommsManager
{
public function getEncoder()
{
return new MegaApptEncoder();
}
public function getFooter()
{
return "mega -- footer ";
}
public function getHead()
{
return "mega -- header ";
}
}
image.png
3.抽象工厂模式
如果上面增加了联系人和代办事项两个类别,要求工厂要求创建一系列的类,可以在抽象类的接口声明相关方法,也可以根据传入的参数判断。
抽象工厂模式.pngabstract class ApptEncode
{
abstract function encode();
}
abstract class TtdEncode
{
abstract function encode();
}
abstract class ContactEncode
{
abstract function encode();
}
//Bloggs编码格式
class BloggsApptEncoder extends ApptEncode
{
function encode()
{
echo ' appointment -- bloggs';
}
}
class BloggsTtdEncoder extends ApptEncode
{
function encode()
{
echo ' ttd -- bloggs';
}
}
class BloggsContactEncoder extends ApptEncode
{
function encode()
{
echo 'contact -- bloggs';
}
}
//Mega编码格式
class MegaApptEncoder extends ApptEncode
{
function encode()
{
echo ' appointment -- Mega';
}
}
//工厂方法模式把创建者类与要生产的产品类分离开来,创建者是一个工厂类,其中定义了用于生产产品对象的类方法。如果没有提供默认实现就要创建者类的子类来实例化
//一般情况下一个创建者的子类对应一个产品。
abstract class CommsManager
{
abstract public function getHead();
abstract public function getFooter();
//创建一系列的对象,不是一个
abstract public function getApptEncoder();
abstract public function getThdEncoder();
abstract public function ContactEncoder();
}
//Mega和这个相似
class BloggsCommsManager extends CommsManager
{
public function getApptEncoder()
{
return new BloggsApptEncoder();
}
public function getThdEncoder()
{
return new BloggsTtdEncoder();//
}
public function ContactEncoder()
{
return new BloggsContactEncoder();
}
public function getFooter()
{
return "Bloggs -- footer ";
}
public function getHead()
{
return "Bloggs -- header ";
}
}
4.原型模式
问题.png可以用抽象工厂模式实现,如下
image.png
但是会产生巨大的平行继承体系,而且不那么灵活。可以原型模式。
class Resource{};
class FishResource extends Resource{};
class Sea{
public $resource;
public function __construct(Resource $resource)
{
$this->resource = $resource;
}
public function __clone()
{
// TODO: Implement __clone() method.
$this->resource = clone $this->resource;
}
}
class ErathSea extends Sea {}
class MarsSea extends Sea{}
class Forest{}
class EarthForest extends Forest {}
class MarsForest extends Forest{}
class Plains {}
class EarthPlains extends Plains {}
class MarsPlains extends Plains{}
class TerrainFactory
{
private $sea;
private $forest;
private $plains;
function __construct(Sea $sea, Plains $plains,Forest $forest)
{
$this->sea = $sea;
$this->forest = $forest;
$this->plains = $plains;
}
public function getSea()
{
return clone $this->sea;
}
public function getForeset()
{
return clone $this->forest;
}
public function getPlains()
{
return clone $this->plains;
}
}
//如果生成的对象是由其他的对象组成的,代码具有灵活性,假设sea对象都能包含Resource对象(FishResource ,OilResource。
设计模式经常相互包含,比如抽象工厂模式里面包含工厂方法模式。下面是一个单例模式和抽象工厂模式相结合而且常见的例子。
class config {
static $config = ['codeType' => 'BloggsCommsManager'];
}
class Setting{
private $props = array();
private static $instance;
//设置为私有不能在外部初始化
private function __construct()
{
}
public static function getInstance()
{
if (!self::$instance instanceof self) {
self::$instance = new self();
}
return self::$instance;
}
//防止clone,设置为私有
private function __clone()
{
}
public function getEncoder()
{
//假设根据配配置来的
$class = config::$config['codeType'];
if (class_exists($class) && $class instanceof CommsManager) {
return new $class();
}else{
return new BloggsCommsManager();
}
}
}
$commsManager = Setting::getInstance()->getEncoder();
$commsManager->getApptEncoder()->encode();
网友评论