PHP需要单例模式吗?
2009-03-19先看看什么是单例模式。
单例模式的存在在一些情况下是比较有意义的,如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
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意图:
将一个类的接口转换成客户希望的另外一个接口。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定义:
提供一个统一的接口去访问多个子系统的多个不同的接口。外观模式定义了一个高层次的接口,使得子系统更容易被使用。
外观类
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中的例子就特别有代表性。
[设计模式]责任链模式
2008-05-25责任链模式属于行为型设计模式中的一种。
责任链模式避免将发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并沿着这条链传递请求,直到有对象处理为止。

Handler:传递者接口,定义一个处理请求的接口;实现链中下一个对象(可选)
ConcreteHandler:具体传递者,处理它所负责的请求;可以访问链中下一个对象,如果可以处理请求就处理它,否则将请求传递给下一个对象。
Client:客户端应用程序。
实际生活中的例子:
员工请假,部门经理可以批3天以下的假期,中心总监可批5天以下的假期,副总裁可批10天以下的假期,CEO可以批20天以下假期,超过20天需要开会决定。
示例:
// "Handler"
//传递者抽象类
abstract class Handler
{
protected Handler successor; //维护它的下一个处理对象
public void SetSuccessor(Handler successor)
{
this.successor = successor;
}
//处理方法
public abstract void HandleRequest(int request);
}
具体传递者
// 部门经理
class ConcreteHandler1 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 0 && request <= 3)
{
Console.WriteLine(" {1} 天假期已由部门经理批示",
this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
// 中心总监
class ConcreteHandler2 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 4 && request < 6)
{
Console.WriteLine(" {1} 天假期已由中心总监批示",
this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
//副总裁
class ConcreteHandler3 : Handler
{
public override void HandleRequest(int request)
{
if (request >=6 && request < 11)
{
Console.WriteLine(" {1} 天假期已由副总裁批示",
this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
//CEO
class ConcreteHandler4 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 11 && request < 21)
{
Console.WriteLine(" {1} 天假期已由CEO批示",
this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
//开会决定
class ConcreteHandler5 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 21)
{
Console.WriteLine(" {1} 天假期需要开会决定",
this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
客户端调用
static void Main()
{
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
Handler h4 = new ConcreteHandler4();
Handler h5 = new ConcreteHandler5();
h1.SetSuccessor(h2);
h2.SetSuccessor(h3);
h3.SetSuccessor(h4);
h4.SetSuccessor(h5);
int[] requests = { 2, 5, 14, 22 };
foreach (int request in requests)
{
h1.HandleRequest(request);
}
Console.Read();
}
策略模式
2008-05-13Strategy策略模式是属于设计模式中对象行为型模式,主要是定义一系列的算法,把这些算法一个个封装成单独的类.
它的UML图

Strategy是一个策略类,其中定义一个或多个算法接口
ConcreteStrategy是实现算法接口的具体策略类
Context是上下文应用
比如,我要从龙阳路去浦东国际机场,我可以选择坐公交、可以选择打车、可以选择坐磁悬浮。 实现该接口(算法)的具体类 public void ToDo() #endregion public void ToDo() #endregion public class ByTrain : IToAerodrome public void ToDo() #endregion /// <summary> /// <summary> context
这里的乘车方式就是一个可变的,因此独立为一接口
如策略接口
public interface IToAerodrome
{
void ToDo();
}
public class ByBus : IToAerodrome
{
#region IToAerodrome 成员
{
Console.WriteLine("乘坐公交车去机场");
}
}
public class ByTaxi : IToAerodrome
{
#region IToAerodrome 成员
{
Console.WriteLine("我乘坐出租车去机场");
}
}
{
#region IToAerodrome 成员
{
Console.WriteLine("坐每小时200公里的磁悬浮");
}
}
public class ToAerodromeStrategy
{
IToAerodrome _ToAerodrome;
/// <summary>
/// 构造函数,以实现IToAerodrome的类实体为参数
/// </summary>
/// <param name="toAerodrome"></param>
public ToAerodromeStrategy(IToAerodrome toAerodrome)
{
_ToAerodrome = toAerodrome;
}
/// 改变当前的策略
/// </summary>
/// <param name="toAerodrome"></param>
public void ChangeStrategy(IToAerodrome toAerodrome)
{
_ToAerodrome = toAerodrome;
}
/// 执行方法
/// </summary>
public void Go()
{
_ToAerodrome.ToDo();
}
}
static void Main(string[] args)
{
ToAerodromeStrategy to = new ToAerodromeStrategy(new ByBus());
to.Go();
Console.WriteLine("我要改坐磁悬浮");
to.ChangeStrategy(new ByTrain());
to.Go();
Console.Read();
}




