PHP需要单例模式吗?

2009年03月19日 10:33 上午  |  分类:Develop

先看看什么是单例模式
单例模式的存在在一些情况下是比较有意义的,如BlogEngine的站点配置就是采用的单例模式,而且它的载入和保存的代码是相当经典的,有兴趣可以看看它的源代码。
由于asp.net是编译型的,所以单例一直会存在于这个应用程序的生命周期里,真正可以做到这个实例在应用程序生命周期中的唯一性。

php的单例模式的实现大致如下:

class Stat{
static $instance = NULL;

static function getInstance(){
if(self::$instance == NULL){
self::$instance = new Stat();
}
return self::$instance;
}

private function __construct(){
}

private function __clone(){
}

function sayHi(){
return "The Class is saying hi to u ";
}
}
echo Stat::getInstance()->sayHi();

代码来自:http://www.cnblogs.com/cocowool/archive/2009/03/18/1415660.html
但,PHP是一种解释型的语言,在这里用单例好像看不出实际的用处,一旦整个页面执行完,变量也就消失了。

static function getInstance(){
if(self::$instance == NULL){
self::$instance = new Stat();  //这里随着页面的重载会再次执行
}
return self::$instance;
}

我接触PHP时间不长,以上写出来的只是在C#与PHP二种不同语言环境下对单例模式的认知,也许这个例子只是为了说明模式可以用很多种语言来实现,但并不意味着在各种语言环境下都能真正起作用。
asp.net中的单例是在整个应用程序域唯一。PHP中的单例只在整个页面周期内唯一

装饰者模式

2008年06月10日 4:31 下午  |  分类:Develop


Component
抽象组件,在以下例子中为Photo类
ConcreteComponent
具体组件,在以下例子中为MyPhoto类,继承自Photo类

Decorator
装饰者抽象组件,在内部维护一个Photo的实例
装饰者组件也继承自Photo类,以下例子中为PhotoFrame抽象类
ConcreteDecorator
具体装饰者,如矩形相框、椭圆相框等。
在重写Photo类相关方法的同时,会附加其它的方法


class Program
{
static void Main(string[] args)
{
//先创建一个影集
Photo photo = new MyPhoto("黄山之行影集");
//用一个矩形相框装饰它
photo = new RectangleFrame(photo);
//再用一个椭圆相框装饰它
photo = new EllipseFrame(photo);
photo.GetDescription();
}
}

/// <summary>
/// 相片基类
/// </summary>
public abstract class Photo
{
public Photo() { }
protected string _description = "未命名";
public Photo(string description)
{
_description = description;
}
/// <summary>
/// 返回相片的描述
/// </summary>
public abstract void GetDescription();
}

/// <summary>
/// 具体相片
/// </summary>
public class MyPhoto : Photo
{
public MyPhoto(string description)
: base(description)
{

}

public override void GetDescription()
{
Console.WriteLine(_description);
}
}

/// <summary>
/// 装饰类,相框
/// </summary>
public abstract class PhotoFrame : Photo
{
private Photo _photo = null;
public PhotoFrame(Photo p)
{
_photo = p;
}
public override void GetDescription()
{
if (_photo != null)
_photo.GetDescription();
}
}

/// <summary>
/// 具体的相框,矩形相框
/// </summary>
public class RectangleFrame : PhotoFrame
{
public RectangleFrame(Photo p) : base(p)
{

}
public override void GetDescription()
{
base.GetDescription();
Console.WriteLine("--已加上矩形相框");
}
}

/// <summary>
/// 具体的相框,椭圆相框
/// </summary>
public class EllipseFrame : PhotoFrame
{
public EllipseFrame(Photo p)
: base(p)
{
}
public override void GetDescription()
{
base.GetDescription();
Console.WriteLine("--加上漂亮的椭圆边框");
}
}

执行结果:


所有代码下载:
Decorator.rar (794.00 bytes)

适配器模式

2008年05月28日 9:33 上午  |  分类:Develop

意图:
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

Target
定义一个目标接口,可以是一个接口也可以是一个抽象类.
Adapter
适配器类,它要实现目标接口且维护一个被适配对象的实例.
Adaptee
被适配对象
Client
客户端调用
很典型的例子就是笔记本电脑的电源适配器,它通过适配器将直流电转化为笔记本电脑所需的标准电压.


class Program
{
static void Main(string[] args)
{
ITarget t = new Adapter(new Adaptee());
t.WriteEvent(DateTime.Now.ToString());
Console.Read();
}
}

/// <summary>
/// 目标接口
/// </summary>
interface ITarget
{
void WriteEvent(string msg);
}

/// <summary>
/// 适配器类,它要实现目标接口且维护一个被适配对象的实例
/// </summary>
class Adapter : ITarget
{
Adaptee adaptee;
public Adapter(Adaptee a)
{
adaptee = a;
}
/// <summary>
/// 实现目标接口的方法,将它委托给被适配对象去执行,而这一切对客户来说是解耦的
/// </summary>
/// <param name="msg"></param>
public void WriteEvent(string msg)
{
adaptee.AdapteeWrite(msg);
}

}

/// <summary>
/// 被适配对象
/// </summary>
class Adaptee
{
public void AdapteeWrite(string msg)
{
Console.WriteLine("这里适配器在起作用:"+msg);
}
}

适配器模式又分为对象适配与类适配,对象适配通过组合实现,如上面的例子.类适配通过继承来实现.

输出结果

外观模式

2008年05月26日 11:04 下午  |  分类:Develop

定义:
提供一个统一的接口去访问多个子系统的多个不同的接口。外观模式定义了一个高层次的接口,使得子系统更容易被使用。

UML示意图

外观类
1、知道哪些子系统,知道处理哪些请求
2、将客户的请求传递给子系统处理

子系统类
1、实现了子系统的功能
2、处理由外观类传过来的任务
3、子系统无需知道外观类,在任何地方也没有引用外观类。

现实中的例子:
  我们去餐厅吃饭,只需将菜单传递给服务员即可。服务员就是这里的外观类,服务员会将请求传递给厨房里的厨师、传菜工等服务生。
以下代码取自DoFactory

using System;

namespace DoFactory.GangOfFour.Facade.Structural
{

//客户端调用

class MainApp
{
public static void Main()
{
Facade facade = new Facade();

facade.MethodA();
facade.MethodB();
Console.Read();
}
}

// 子系统1

class SubSystemOne
{
public void MethodOne()
{
Console.WriteLine(" SubSystemOne Method");
}
}

// 子系统2

class SubSystemTwo
{
public void MethodTwo()
{
Console.WriteLine(" SubSystemTwo Method");
}
}

// 子系统3

class SubSystemThree
{
public void MethodThree()
{
Console.WriteLine(" SubSystemThree Method");
}
}

// 子系统4

class SubSystemFour
{
public void MethodFour()
{
Console.WriteLine(" SubSystemFour Method");
}
}

// 外观类

class Facade
{
//外观类知道它要处理哪些子系统
SubSystemOne one;
SubSystemTwo two;
SubSystemThree three;
SubSystemFour four;

public Facade()
{
one = new SubSystemOne();
two = new SubSystemTwo();
three = new SubSystemThree();
four = new SubSystemFour();
}
//外观类中某些方法会委托给子系统去执行
public void MethodA()
{
Console.WriteLine("\nMethodA() ---- ");
one.MethodOne();
two.MethodTwo();
four.MethodFour();
}

public void MethodB()
{
Console.WriteLine("\nMethodB() ---- ");
two.MethodTwo();
three.MethodThree();
}
}
}

外观模式提供了一个简单的公有接口去处理复杂的子系统,并且没有减少子系统的功能。
它避免了客户端直接去同复杂的子系统去直接交互。
当然,如果你需要高级的功能,也可直接去调用子系统。

对于外观模式,head first中的例子就特别有代表性。