+ -
当前位置:首页 → 问答吧 → 设计模式的PHP5代码示例

设计模式的PHP5代码示例

时间:2007-02-26

来源:互联网

设计模式归类

分类源自: Bruce Eckel之《Thinking in Patterns with Java》

接口: interface, 像什么的一种表述, 包括若干抽象方法, JAVA或PHP5中的interface关键字同样意思

1 控制对象的数量
  1) Singleton:
      通过种种手段保证系统中只能存在唯一对象
      适用于: 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时
  2) 对象池:
      相关模式有 Flyweight, proxy, Factory, Immutable.

2 对象解藕
  1) Proxy
      访问控制
      适用于:
      a) 远程代理: 为一个对象在不同的地址空间提供局部代表.
      b) 虚代理: 推迟创建开销很大的对象的时机.
      c) 保护代码: 控制对原始对象的访问.
      4) 智能代理: 在访问对象执行一些附加操作,如统计数据库访问次数等.
  2) State:
      改变对象行为
      把不同状态下的不同行为以多态方式封装,代替if else判断
  3) Iterator: 解藕容器设计与元素遍历
      所有容器都提供Iterator接口进行遍历

3 分解一般性与特殊性
  1) Strategy:
      在运行时选择特殊部分的算法
  2) Template method
      使用抽象类定义算法的骨架,把不同的行为定义为抽象方法,由子类实现

4 封装对象的创建
  1)Factory
    提供创建对象的方法
    a) Simple Factory:
        把产品进行抽象
        使用工厂类的方法生产产品
    b) Factory Method:
        在Simple Factory的基础上把工厂进行抽象
    c) Abstract Factory:
        在Factory Method的基础上
        工厂生产多类产品

5 特殊创建
  1) Prototype
      复制已有的对象
      有深浅复制之分
  2) Builder 解藕部件的生产和部件的组装
      Builder负责生产部件
      Director负责组装部件

6 太多
  1) Flyweight: 太多对象
      把类设计成可以共享的东西
      相同的对象只创建一份
      通常把类设计成Immutable(不变类)
  2) Decorator: 太多类
      功能变化太多
      共同的接口, 不同的(附加)功能类
      使用构造器进行任意组合, 动态给类增加责职

7 连接不同的类型
  1) Adapter:
      在这两种接口之间创建一个混合接口(混血儿)
  2) Bridge:
      抽象部分,实现部分, 分别发展
      以抽象部分调用实现部分的接口进行桥接

8 复杂的结构
  1) Composite:
      组合:树状结构, 子结构中又有子结构
      提供单个对象和组合对象的统一操作方法

9 系统解藕
  1) Observer:
      当对象发生成变化时通知所有观察者
  2) Mediator:
      通过调停人与其它人打交道

10 降低系统复杂度
  1) Facade
      通过导游小姐,而不是自己去找景点

11 算法分解
  1) Command
      把功能封装成类以便动态调用
  2) Chain of Responsibility
      张三不行换李四,李四不行换王五,直到一个行为止

12 记录对象状态
  1) Memento
      使用任何介质储存对象,以便需要时还原

13 复杂交互
  1) Visitor
      双动态绑定
      每一类访问者都正确的处理各类被访问者

14 多种语言
  1) Interpreter
      上下文语言解析器

初步完成,不断改进中
更新地址: http://nyim.blog.163.com/
环境: php 5.1.4 + windows xp + apache 2.0

[ 本帖最后由 书生 于 2007-8-23 19:46 编辑 ]

作者: 书生   发布时间: 2007-02-25

1产品:
复制PHP内容到剪贴板
PHP代码:

<?php
interface Car {
  function run();
}

class BMWCar implements Car {
  function run(){echo "BMW running \n";}
}
class FordCar implements Car {
  function run(){echo "Ford car running \n";}
}

?>

2简单工厂
复制PHP内容到剪贴板
PHP代码:
/**
 * 简单工厂
 *
 */
class SimpleCarFactory {

  /**
   * 工厂方法
   *
   * @param string $type
   * @return Car
   */
  static function create($type){
    if ($type=='BMW') {
        return new BMWCar();
    }elseif ($type=='Ford') {
        return new FordCar();
    }
    throw new Exception("not such car type $type");
  }
}

$car=SimpleCarFactory::create('BMW');
$car->run();

3将工厂进行抽象
复制PHP内容到剪贴板
PHP代码:
interface Factory {
  /**
   * @return Car
   */
  function create();
}

class BMWFactory implements Factory {

  function create(){return new BMWCar();}
}

class FordFactory implements Factory {

  function create() {return new FordCar();}
}

function carTest(Factory $factory){
  echo '<pre>';
  $car=$factory->create();
  $car->run();
}

carTest(new BMWFactory());
carTest(new FordFactory());

[ 本帖最后由 书生 于 2007-2-26 13:59 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php
interface Truck {
  function run();
}

interface SportCar {
  function compete();
}

class DongfengTruck implements Truck {
  function run(){
    echo "Dongfeng truck running\n";
  }
}

class DongfengSportCar implements SportCar {
  function compete(){
    echo "Dongfeng sport car running\n";
  }
}

class FordTruck implements Truck {
  function run(){
    echo "Ford truck running\n";
  }
}

class FordCar implements SportCar {
  function compete(){
    echo "Ford car running\n";
  }
}

interface Factory {
  /**
   * @return Truck
   */
  function createTruck();
  /**
   * @return SportCar
   */
  function createCar();
}

class FordFactory implements Factory {
  function createTruck(){
    return new FordTruck();
  }
  function createCar(){
    return new FordCar();
  }
}

class DongfengFactory implements Factory {
  function createTruck(){
    return new DongfengTruck();
  }
  function createCar(){
    return new DongfengSportCar();
  }
}

function factoryTest(Factory $factory){
  $truck=$factory->createTruck();
  $car=$factory->createCar();
  echo '<pre>';
  $truck->run();
  $car->compete();
}

factoryTest(new FordFactory());
factoryTest(new DongfengFactory());
?>

[ 本帖最后由 书生 于 2007-2-26 14:27 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制已有的对象

由于php5使用引用传递对象,所以等号并不能复制对象.


1: 浅复制 clone关键字
复制PHP内容到剪贴板
PHP代码:
class Dog {
  private $name;
  /**
   * 构造器
   *
   * @param string $name
   */
  function __construct($name){
    $this->name=$name;
  }
  /**
   * 获取狗名,调试之用
   *
   * @return string
   */
  function getName(){
    return $this->name;
  }
}
  $pet=new Dog('Spot');
  echo '<pre>';
  echo $pet,": class=".get_class($pet)," name=".$pet->getName(),"\n";
  $clone=clone $pet;
  echo $clone,": class=".get_class($clone)," name=".$clone->getName(),"\n";

2: 魔术方法深复制
复制PHP内容到剪贴板
PHP代码:
class Phone {
  private $id;
  function __construct($id){
    $this->id=$id;
  }
  function getId(){
    return $this->id;
  }
}

class Man {
  private $name;
  /**
   * @var Phone
   */
  private $phone;
  function __construct($name){
    $this->name=$name;
  }
  function setPhone(Phone $phone){
    $this->phone=$phone;
  }
  /**
   * @return Phone
   */
  function getPhone(){
    return $this->phone;
  }
  function getName(){
    return $this->name;
  }
  /**
   * 克隆时调用的魔术方法
   *
   */
  function __clone(){
    //将手机一并复制,
    //如果注释掉,克隆人将和原来的人共用一部手机
    $this->phone=clone $this->phone;
  }
}

  $phone=new Phone('2110');
  $man=new Man('Nicholas');
  $man->setPhone($phone);

  echo '<pre>';
  echo "\n$man is ".get_class($man)." has name: ".$man->getName();
  echo "\nhas a:";
  $manPhone=$man->getPhone();
  echo "\n$manPhone is ".get_class($manPhone)." has id: ".$manPhone->getId();
  echo "\n\n\n";
  $cloneMan=clone $man;
  echo "\n$cloneMan is ".get_class($cloneMan)." has name: ".$cloneMan->getName();
  echo "\nhas a:";
  $manPhone=$cloneMan->getPhone();
  echo "\n$manPhone is ".get_class($manPhone)." has id: ".$manPhone->getId();
  echo "\n\n\n";

3: 序列化深复制
复制PHP内容到剪贴板
PHP代码:
class Phone {
  private $id;
  function __construct($id){
    $this->id=$id;
  }
  function getId(){
    return $this->id;
  }
}

class Man {
  private $name;
  /**
   * @var Phone
   */
  private $phone;
  function __construct($name){
    $this->name=$name;
  }
  function setPhone(Phone $phone){
    $this->phone=$phone;
  }
  /**
   * @return Phone
   */
  function getPhone(){
    return $this->phone;
  }
  function getName(){
    return $this->name;
  }
}

  $phone=new Phone('2110');
  $man=new Man('Nicholas');
  $man->setPhone($phone);

  echo '<pre>';
  echo "\n$man is ".get_class($man)." has name: ".$man->getName();
  echo "\nhas a:";
  $manPhone=$man->getPhone();
  echo "\n$manPhone is ".get_class($manPhone)." has id: ".$manPhone->getId();
  echo "\n\n\n";
  /*在内存中序列化并反序列化*/
  $cloneMan=unserialize(serialize($man));
  echo "\n$cloneMan is ".get_class($cloneMan)." has name: ".$cloneMan->getName();
  echo "\nhas a:";
  $manPhone=$cloneMan->getPhone();
  echo "\n$manPhone is ".get_class($manPhone)." has id: ".$manPhone->getId();
  echo "\n\n\n";

[ 本帖最后由 书生 于 2007-2-25 21:22 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

interface Part{
  function work();
}

interface PartFactory{
  /**
   * @return Part
   *
   */
  function build();
}

interface Builder{
  /**
   * @return Cpu
   */
  function buildCpu();
  /**
   * @return MainBoard
   */
  function buildMainBoard();
  /**
   * @return Ram
   */
  function buildRam();
  /**
   * @return VideoCard
   */
  function buildVideoCard();
  /**
   * @return Power
   */
  function buildPower();
}

class Computer {

  private $parts=array();

  function addPart(Part $part){
    $this->parts[]=$part;
  }

  function run(){
    /*@var $part Part*/
    echo '<pre>';
    echo $this," working \n";
    foreach ($this->parts as $part) {
        $part->work();
        echo "\n";
    }
  }
}

class Cpu implements Part {
  function work(){echo 'cpu: '. get_class($this).' running';}
}

class MainBoard implements Part {
  function work(){echo 'main board: '.get_class($this).' running';}
}

class Power implements Part {
  function work(){echo 'power: '.get_class($this).' running';}
}

class Ram implements Part {
  function work(){echo 'ram: '.get_class($this).' running';}
}

class VideoCard implements Part {
  function work(){echo 'video cark: '.get_class($this).' running';}
}

class AmdCpu extends Cpu {}
class AsusMainBoard extends MainBoard {}
class GreatWallPower extends Power {}
class KingMaxRam extends Ram {}
class AtiVideoCard extends VideoCard {}

class Amd implements PartFactory {
  function build(){
    return new AmdCpu();
  }
}

class Asus implements PartFactory {
  function build(){
    return new AsusMainBoard();
  }
}
class GreatWall implements PartFactory {
  function build(){
    return new GreatWallPower();
  }
}
class KingMax implements PartFactory {
  function build(){
    return new KingMaxRam();
  }
}
class Ati implements PartFactory {
  function build(){
    return new AtiVideoCard();
  }
}

/**
 * 负责生产各个零件
 *
 */
class MixedBuilder implements Builder{
  /**
   * @var PartFactory
   */
  private $cpuFactory,$powerFactory,$mainBoardFactory,$videoCardFactory,$ramFactory;
  function __construct(){
    $this->cpuFactory=new Amd();
    $this->mainBoardFactory=new Asus();
    $this->powerFactory=new GreatWall();
    $this->ramFactory=new KingMax();
    $this->videoCardFactory=new Ati();
  }
  function buildCpu(){
    return $this->cpuFactory->build();
  }
  function buildPower(){
    return $this->powerFactory->build();
  }
  function buildMainBoard(){
    return $this->mainBoardFactory->build();
  }
  function buildVideoCard(){
    return $this->videoCardFactory->build();
  }
  function buildRam(){
    return $this->ramFactory->build();
  }
}

/**
 * 负责组装各个零件
 *
 */
class Director {
  /**
   * @var Builder
   */
  private $builder;
  function __construct(Builder $builder){
    $this->builder=$builder;
  }
  /**
   * @return Computer
   *
   */
  function buildComputer(){
    $computer=new Computer();
    $computer->addPart($this->builder->buildPower());
    $computer->addPart($this->builder->buildMainBoard());
    $computer->addPart($this->builder->buildCpu());
    $computer->addPart($this->builder->buildRam());
    $computer->addPart($this->builder->buildVideoCard());
    return $computer;
  }
}

//builder目的,使部件的生产与组装解耦
//部件零售者,处理构置零件
$builder=new MixedBuilder();
//装机人,处理装配顺序
$director=new Director($builder);

$computer=$director->buildComputer();

$computer->run();
?>

[ 本帖最后由 书生 于 2007-2-26 15:23 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:
final class SuperMan {

  private static $self;

  private $name;

  /**
   * 私有构造函数,防止随便创建
   *
   * @param string $name
   */
  private function __construct(){
  }
  /**
   * 召唤超人的唯一方法
   *
   * @return SuperMan
   */
  static function call(){
    if (!self::$self) {
        self::$self=new SuperMan();
    }
    return self::$self;
  }
  /**
   * 调试用方法
   * @return string
   */
  function getName(){
    return $this->name;
  }
  /**
   * 调试用方法
   *
   * @param string $name
   */
  function setName($name){
    $this->name=$name;
  }

  /**
   * 关闭复制
   *
   */
  function __clone(){
    throw new Exception("超人不能克隆");
  }

  /**
   * 关闭序列化
   *
   */
  function __sleep(){
    throw new Exception("超人不能保存");
  }

  /**
   * 关闭反序列化
   *
   */
  function __wakeup(){
    throw new Exception("超人不能恢复");
  }
}

echo '<pre>';
  $superA=SuperMan::call();
  $superA->setName('Super Man');
  $superB=SuperMan::call();
  echo $superA,'      ',$superA->getName(),"\n";
  echo $superB,'      ',$superB->getName(),"\n\n\n";
  SuperMan::call()->setName("Bat Man");
  $superA=SuperMan::call();
  $superB=SuperMan::call();
  echo $superA,'      ',$superA->getName(),"\n";
  echo $superB,'      ',$superB->getName(),"\n\n\n";

[ 本帖最后由 书生 于 2007-2-26 08:51 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:
interface Fighter {

  function fight();

  function killSelf();
}

class JapaneseFilter implements Fighter {

  function fight(){
    echo __CLASS__.' fighting',"\n";
  }

  function killSelf(){
    echo __CLASS__.' dying',"\n";
  }
}

class NoKillSelfProxy implements Fighter {
  /**
   * @var Fighter
   */
  private $fighter;

  function __construct(Fighter $fighter){
    $this->fighter=$fighter;
  }

  function fight(){
    $this->fighter->fight();
  }

  function killSelf(){
    echo 'self kill not allow',"\n";
  }
}


function fighterAction(Fighter $fighter){
  echo '<pre>';
  $fighter->fight();
  $fighter->killSelf();
  echo '</pre>';
}


$jf=new JapaneseFilter();
$pf=new NoKillSelfProxy($jf);

fighterAction($jf);
fighterAction($pf);

[ 本帖最后由 书生 于 2007-2-26 13:28 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

interface WhatIHave {

  function haveOp();
}

interface WhatIWant {

  function wantOp();
}

class Adapter implements WhatIWant {
  /**
   * @var WhatIHave
   */
  private $have;
  function __construct(WhatIHave $have){
    $this->have=$have;
  }

  function wantOp(){
    $this->have->haveOp();
  }
}

class ClassHad implements WhatIHave {
  function haveOp(){
    echo 'have op';
  }
}

function functionHad (WhatIWant $want){
  $want->wantOp();
}

$have=new ClassHad();
$want=new Adapter($have);

//迁就原有的接口,只能采用适配器类来处理.
functionHad($want);
?>

[ 本帖最后由 书生 于 2007-2-26 16:56 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

class Tree {
  private $branch;
  function setBranch(Branch $branch){
    $this->branch=$branch;
  }
  function __toString(){
    return "Tree: has ".$this->branch->__toString();
  }
}

class Branch {
  private static $count=0;

  private $id;
  private $branches;
  private $leaves;

  function __construct(){
    $this->id= ++self::$count;
  }
  function getId(){
    return $this->id;
  }
  function addChild(Branch $branch){
    $this->branches[]=$branch;
  }
  function addLeaf(Leaf $leaf){
    $this->leaves[]=$leaf;
  }

  function __toString(){
    $str= 'Branch '.$this->id;
    if (count($this->branches)>0) {
        $str.=' Has branches: ';
        foreach ($this->branches as $branch) {
            $str.=$branch->__toString()."\n";
        }
    }
    if (count($this->leaves)>0) {
        $str.=' Has leaves';
        foreach ($this->leaves as $leaf) {
            $str.=$leaf->__toString()."\n";
        }
    }
    return $str;
  }
}

class Leaf {

  private static $count=0;
  private $id;

  function __construct(){
    $this->id= ++self::$count;
  }
  function __toString(){
    return ' Leaf '.$this->id;
  }
}

$branch=new Branch();//树枝
$branch->addChild(new Branch());//树枝上的树枝
$branch->addLeaf(new Leaf());//树枝上的叶子
$tree=new Tree();//树
$tree->setBranch($branch);//树的树枝
echo '<pre>',$tree;
?>

[ 本帖最后由 书生 于 2007-2-26 17:38 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

interface Tea {
  function getDesc();
  function getPrice();
}

class BlackTea implements Tea {

  function getDesc(){
    return " BlackTea ";
  }
  function getPrice(){
    return 6;
  }
}

class GreanTea implements Tea {

  function getDesc(){
    return " GreanTea ";
  }
  function getPrice(){
    return 8;
  }
}

class SugarTea implements Tea {
  /**
   * @var Tea
   */
  private $tea;
  function __construct(Tea $tea){
    $this->tea=$tea;
  }
  function getDesc(){
    return ' sugar '.$this->tea->getDesc();
  }
  function getPrice(){
    return 1+$this->tea->getPrice();
  }
}

class MilkTea implements Tea {
  /**
   * @var Tea
   */
  private $tea;
  function __construct(Tea $tea){
    $this->tea=$tea;
  }
  function getDesc(){
    return ' milk '.$this->tea->getDesc();
  }
  function getPrice(){
    return 2+$this->tea->getPrice();
  }
}
echo '<pre>';

//绿茶,加糖,加牛奶
$tea=new MilkTea(new SugarTea(new GreanTea()));
echo $tea->getDesc(),'   $',$tea->getPrice();
echo "\n\n\n\n";
//红茶,加牛奶
$tea=new MilkTea(new BlackTea());
echo $tea->getDesc(),'   $',$tea->getPrice();
echo "\n\n\n\n";
//绿茶加糖
$tea=new SugarTea(new GreanTea());
echo $tea->getDesc(),'   $',$tea->getPrice();
echo "\n\n\n\n";
?>

[ 本帖最后由 书生 于 2007-2-26 18:00 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php
/**
 * 抽象
 */
interface Front {

  function service1();
  function service2();
}

/**
 * 实现
 *
 */
interface Back {

  function implement1();
  function implement2();
}

class ServiceA implements Front {
  /**
   * @var Back
   */
  private $back;

  function __construct(Back $back){
    $this->back=$back;
  }

  function service1(){
    $this->back->implement1();
  }
  function service2(){
    $this->back->implement1();
    $this->back->implement2();
  }
}

class ServiceB implements Front {
  /**
   * @var Back
   */
  private $back;
  function __construct(Back $back){
    $this->back=$back;
  }
  function service1(){
    $this->back->implement2();
  }
  function service2(){
    $this->back->implement2();
    $this->back->implement1();
  }
}

class ImplA implements Back {
  function implement1(){
    echo "ImpA.implement1\n";
  }
  function implement2(){
    echo "ImpA.implement2\n";
  }
}

class ImplB implements Back {
  function implement1(){
    echo "ImpB.implement1\n";
  }
  function implement2(){
    echo "ImpB.implement2\n";
  }
}

function bridge_test(Front $front){
  echo "<pre>1:\n";
  $front->service1();
  echo "\n\n2:\n";
  $front->service2();
}

//通过接口桥接不同的抽象与实现
$front=new ServiceA(new ImplB());
bridge_test($front);
?>

[ 本帖最后由 书生 于 2007-2-27 20:54 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

/**
 * 共享相同对象以减少对象创建的数量,
 *
 */
class FlyWeight {

  /**
   * fly weight pool
   *
   * key value pair
   *
   * @var array
   */
  private static $pool=array();

  private $word;

  /**
   * 防止外部创建
   *
   */
  private function __construct($word){
    $this->word="<b>$word</b>";
  }

  /**
   * 统一获取方法
   *
   * @param string $word
   * @return FlyWeight
   */
  static function getFlyWeight($word){
    if (!isset(self::$pool[$word])) {
        self::$pool[$word]=new FlyWeight($word);
    }
    return self::$pool[$word];
  }

  static function count(){
    return count(self::$pool);
  }

  function display(){
    echo $this->word;
  }

  function __clone(){
    throw new Exception("not clone");
  }

  function __wakeup(){
    throw new Exception("not unserialize");
  }
}

$a=FlyWeight::getFlyWeight('a');
$b=FlyWeight::getFlyWeight('b');
$c=FlyWeight::getFlyWeight('a');

$a->display();
$b->display();
$c->display();
echo '<br />',FlyWeight::count(),'<br />';
echo $a,'<br />',$b,'<br />',$c
?>

[ 本帖最后由 书生 于 2007-2-27 20:55 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

class Complex1 {
  function op1(){echo 'Complex1.op1';}
  function op2(){echo 'Complex1.op2';}
}

class Complex2 {
  function op3(){echo 'Complex2.op3';}
  function op4(){echo 'Complex2.op4';}
}

class Facade {
  static function operation1(){
    $c1=new Complex1();
    $c1->op1();
    $c2=new Complex2();
    $c2->op4();
  }
  static function operation2(){
    $c2=new Complex2();
    $c2->op3();
  }
}

Facade::operation1();
Facade::operation2();
?>

[ 本帖最后由 书生 于 2007-2-27 20:55 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

/**
 * 为了不存在封装,Originator与memento之间要能够互相访问私有变量
 * 由于php没有内部类,也没有友元. memento只能由关联数组进行处理了.
 *
 */
class Originator {
  private $v1,$v2,$v3,$v4;

  function getV1(){
    return $this->v1;
  }
  function setV1($v1){
    $this->v1=$v1;
  }

  function getMemento(){
    return array($this->v1,$this->v2,$this->v3,$this->v4,);
  }

  function setMemento($data){
    $this->v1=$data[0];
    $this->v2=$data[1];
    $this->v3=$data[2];
    $this->v4=$data[3];
  }
}

$ori=new Originator();
$ori->setV1('original');

//保存
$data=$ori->getMemento();

//修改
$ori->setV1('new');
echo $ori->getV1(),'<br />';

//还原
$ori->setMemento($data);
echo $ori->getV1();
?>

[ 本帖最后由 书生 于 2007-2-27 20:57 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

/**
 * 观察者
 *
 * 参考java.util.Observable
 */
interface Observer {

  function update(Observable $o,$arg);
}

/**
 * 被观察者
 *
 * 参考java.util.Observable
 */
abstract class Observable {
  /**
   * @var array
   */
  private $observers=array();
  private $changed=false;
  private $toBeDelete;

  /**
   * 增加观察者
   *
   * @param Observer $o
   */
  function addObserver(Observer $o){
    if (!in_array($o,$this->observers)) {
        $this->observers[]=$o;
    }
  }

  /**
   * @return int
   */
  function countObserver(){
    return count($this->observers);
  }

  /**
   * 删除特定观察者
   *
   * @param Observer $o
   */
  function deleteObserver(Observer $o){
    $this->toBeDelete=$o;
    $this->observers=array_filter($this->observers,array($this,'filter'));
    $this->toBeDelete=null;
  }

  /**
   * 清除所有观察者
   *
   */
  function deleteAllObserver(){
    $this->observers=array();
  }

  /**
   * 是否改变
   *
   * @return bool
   */
  function hasChanged(){
    return $this->changed;
  }

  /**
   * 改变后通知观察者
   *
   * @param unknown_type $arg
   */
  function notifyObservers($arg=null){
    if ($this->hasChanged()) {
      /*@var $o Observer*/
        foreach ($this->observers as $o) {
            $o->update($this,$arg);
        }
        $this->clearChanged();
    }
  }

  /**
   * 清除变化
   *
   */
  protected function clearChanged(){
    $this->changed=false;
  }

  /**
   * 设置已改变标志
   *
   */
  protected function setChanged(){
    $this->changed=true;
  }

  /**
   * 过滤器实现
   *
   * @param Observer $o
   * @return bool
   */
  private function filter(Observer $o){
    return $this->toBeDelete!=$o;
  }
}

class Clock extends Observable {
  private $timestamp;
  function __construct(){
    $this->timestamp=time();
  }

  function getTimestamp(){
    return $this->timestamp;
  }

  function setTimestamp($timestamp){
    if ($this->timestamp==$timestamp) {
        return ;
    }
    $this->timestamp=$timestamp;
    $this->setChanged();
    $this->notifyObservers($timestamp);
  }
}

class Teacher implements Observer {
  function update(Observable $src,$arg){
    if (date('d',$arg)==11) {
        echo date('Y-m-d',$arg),'领工资日期到了',"\n";
    }else {
        echo date('Y-m-d',$arg),'不是工资日期到了',"\n";
    }
  }
}

echo '<pre>';

$clock=new Clock();
$clock->addObserver(new Teacher());
$clock->setTimestamp(mktime(1,2,2,2,10,2007));
$clock->setTimestamp(mktime(1,2,2,2,11,2007));
?>

[ 本帖最后由 书生 于 2007-2-27 20:57 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

class Request {
  private $attr=array();
  function setAttr($name,$value){
    $this->attr[$name]=$value;
  }
  function getAttr($name){
    if (array_key_exists($name,$this->attr)) {
        return $this->attr[$name];
    }
    return null;
  }
}

interface Handler {

  /**
   * 由处理器决定是否进行下一个处理.
   *
   * @param Request $req
   * @param Chain $chain
   */
  function process(Request $req,Chain $chain);
}

class Chain {

  private $handlers;

  function doChain(Request $req){
    if (count($this->handlers)>0) {
        $handler=array_shift($this->handlers);
      /*@var $handler Handler*/
      $handler->process($req,$this);
    }
  }

  function addHandler(Handler $handler){
    $this->handlers[]=$handler;
  }
}

class HttpHandler implements Handler {
  function process(Request $req,Chain $chain){
    echo "handling http request\n";
    $chain->doChain($req);
  }
}

class BufferHandler implements Handler {
  function process(Request $req,Chain $chain){
    echo "handling buffer\n";
    $chain->doChain($req);
  }
}

echo '<pre>';

$req=new Request();
$chain=new Chain();
$chain->addHandler(new HttpHandler());
$chain->addHandler(new BufferHandler());
$chain->doChain($req);
?>

[ 本帖最后由 书生 于 2007-2-27 20:58 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

/**
 * 其实就是把一个调用使用类进行封装
 *
 */
interface Command {
  function execute();
}

class Macro {

  private $cmds;
  function addCommand(Command $cmd){
    $this->cmds[]=$cmd;
  }

  function run(){
    /*@var $cmd Command*/
    foreach ($this->cmds as $cmd) {
        $cmd->execute();
    }
  }
}

class Hello implements Command {
  function execute(){
    echo "Hello ";
  }
}

class World implements Command {
  function execute(){
    echo "World\n";
  }
}

echo '<pre>';
$macro=new Macro();
$macro->addCommand(new Hello());
$macro->addCommand(new World());
$macro->run();
?>

[ 本帖最后由 书生 于 2007-2-28 18:33 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

interface State {
  function act();
}

class Prince implements State {
  function act(){
    echo "Sweet Heart\n";
  }
}

class Frog implements State {
  function act(){
    echo "Kua Kua\n";
  }
}

class Creature {
  /**
   * @var State
   */
  private $state;
  function __construct(){
    $this->state=new Prince();
  }

  function curse(){
    $this->state=new Frog();
  }

  function kiss(){
    $this->state=new Prince();
  }

  /**
   * 自动根据自己的状态进行问候
   *
   */
  function greeting(){
    $this->state->act();
  }
}
echo '<pre>';
$frogPrince=new Creature();
$frogPrince->greeting();
$frogPrince->curse();
$frogPrince->greeting();
$frogPrince->kiss();
$frogPrince->greeting();
?>

[ 本帖最后由 书生 于 2007-2-28 18:33 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php
/**
 * 比较器
 *
 * @package lib
 */
interface Comparator {

  /**
   * compare to value, return integer
   *
   * less  ,  less than 0
   * greater , greater than 0
   * equal ,    0
   * 比较函数必须在第一个参数被认为小于,等于或大于
   *      第二个参数时分别返回一个小于,等于或大于零的整数。
   *
   * @param mixed $left
   * @param mixed $right
   * @return integer
   */
  function compare($left,$right);
}

/**
 * sort by php library, search binary
 *
 * @package lib
 */
class Arrays {
  /**
   * return the sorted index base array
   *
   * @param array $arr
   * @param Comparator $c
   * @return bool if sort success
   */
  public static function sort(&$arr,Comparator $c){
    return usort($arr,array($c,'compare'));
  }

  /**
   * array must be sorted by Arrays::sort
   * @param array $arr
   * @param Comparator $c
   * @return integer index of the search key, if it is contained in the list;
   * otherwise, (-(insertion point) - 1). The insertion point is defined as the
   * point at which the key would be inserted into the list: the index of the
   * first element greater than the key, or list.size(), if all elements in the
   * list are less than the specified key. Note that this guarantees that the
   * return value will be >= 0 if and only if the key is found.
   */
  public static function binarySearch(&$arr,$value,Comparator $c){
    $low=0;
    $high=count($arr)-1;
    while ($low<=$high) {
        $mid=($low+$high)>>1;
        $cmp=$c->compare($value,$arr[$mid]);
        if ($cmp>0) {
            $low=$mid+1;
        }elseif ($cmp<0) {
            $high=$mid-1;
        }else {
            return $mid;
        }
    }
    return -($low+1);
  }
}

//由于排序算法及折半查找算法是稳定的,所不同的是元素之间的大小比较
//所以把元素之间的比较抽象成接口,使得算法可以地运行的时候选用不同比较接口实现

class AlphabetAsc implements Comparator {
  function compare($left,$right){
    return strcasecmp($left,$right);
  }
}

class AlphabetDesc implements Comparator {
  function compare($left,$right){
    return -strcasecmp($left,$right);
  }
}

echo '<pre>';
$arrStr=explode(' ','a b c d e f g h i j');
shuffle($arrStr);
print_r($arrStr);

Arrays::sort($arrStr,new AlphabetAsc());
print_r($arrStr);

echo "\n";
echo Arrays::binarySearch($arrStr,'g',new AlphabetAsc());
?>

[ 本帖最后由 书生 于 2007-2-28 18:34 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

interface Mediator {
  function addColleague(Colleague $c);
  function notifyColleague($arg);
}

interface Colleague {
  function setMediator(Mediator $m);
  /**
   * @return Mediator
   *
   */
  function move($arg);
  function change();
}

class Manager implements Mediator {
  private $colleagues=array();
  function addColleague(Colleague $e){
    $this->colleagues[]=$e;
  }
  function notifyColleague($arg){
    /*@var $c Colleague*/
    foreach ($this->colleagues as $c) {
        $c->move($arg);
    }
  }
}

class Me implements Colleague {
  /**
   * @var Mediator
   */
  private $mediator;
  function setMediator(Mediator $m){
    $this->mediator=$m;
  }
  function move($arg){
    echo $this->mediator," tell me to do something with $arg\n";
  }
  function change(){
    $this->mediator->notifyColleague('my request');
  }
}

class You implements Colleague {
  /**
   * @var Mediator
   */
  private $mediator;
  function setMediator(Mediator $m){
    $this->mediator=$m;
  }
  function move($arg){
    echo $this->mediator," tell you to do something with $arg\n";
  }
  function change(){
    $this->mediator->notifyColleague('your request');
  }
}
echo '<pre>';

$mediator=new Manager();
$c1=new Me();
$c2=new You();
$mediator->addColleague($c1);
$mediator->addColleague($c2);
$c1->setMediator($mediator);
$c2->setMediator($mediator);

$c1->change();//某同事有事要做
$c2->change();//另一同事有事要做
?>

[ 本帖最后由 书生 于 2007-2-28 18:34 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

abstract class Man {
  function live(){
    $this->dress();//衣
    $this->eat();//食
    $this->house();//住
    $this->move();//行
  }

  protected abstract function dress();
  protected abstract function eat();
  protected abstract function house();
  protected abstract function move();
}

class Worker extends Man {

  protected function dress(){
    echo "dress work clothes\n";
  }

  protected function eat(){
    echo "eat work food\n";
  }

  protected function house(){
    echo "live in dorm\n";
  }

  protected function move(){
    echo "work\n";
  }
}

class Beggar extends Man {

  protected function dress(){
    echo "dress clothes with hole\n";
  }

  protected function eat(){
    echo "eat rest food\n";
  }

  protected function house(){
    echo "live in steet\n";
  }

  protected function move(){
    echo "begging\n";
  }
}

echo '<pre>';
$man1=new Worker();
$man2=new Beggar();
$man1->live();
$man2->live();
?>

[ 本帖最后由 书生 于 2007-2-28 18:35 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php
/**
 * 由于php不支持重载,所有visit方法只能使用visit+类名构成.
 *
 */
interface Visitor {
  function visitEmail(Email $mail);
  function visitTele(Tele $tel);
}

interface Visitable {
  function accept(Visitor $v);
}

abstract class AbstractVisitable implements Visitable{
  function accept(Visitor $v){
    //从类名开始,可果找不到则找类
    for ($cls=get_class($this);$cls!=null;$cls=get_parent_class($cls)){
      $method="visit$cls";
      if (method_exists($v,$method)) {
          $v->$method($this);
          return ;
      }
    }
  }
}

/**
 * 可以选择从抽象类进行偷懒
 *
 */
class Email extends AbstractVisitable {
  private $address;
  function __construct(){
    $this->address=rand(10000,99999).'@example.com';
  }
  function getAddress(){
    return $this->address;
  }
}

/**
 * 也可以自己实现
 *
 */
class Tele implements Visitable {
  private $number;
  function __construct(){
    $this->number=rand(10000,99999);
  }
  function getNumber(){
    return $this->number;
  }
  function accept(Visitor $v){
    $v->visitTele($this);
  }
}

class SalesMan implements Visitor {
  function visitTele(Tele $tel){
    echo 'making telephone call to '.$tel->getNumber()." to sale something\n";
  }

  function visitEmail(Email $e){
    echo 'sending email '.$e->getAddress()." to sale something\n";
  }
}

class Inquirer implements Visitor {
  function visitTele(Tele $tel){
    echo 'making telephone call to '.$tel->getNumber()." to query something\n";
  }

  function visitEmail(Email $e){
    echo 'sending email '.$e->getAddress()." to query something\n";
  }
}

echo '<pre>';

$arrVisitable=array(new Tele(),new Tele(),new Email(),new Tele(),new Email());
$visitor1=new SalesMan();
$visitor2=new Inquirer();

/*@var $visitable Visitable*/
foreach ($arrVisitable as $visitable) {
    $visitable->accept($visitor1);//接受访问
    $visitable->accept($visitor2);//接受访问
}
?>

[ 本帖最后由 书生 于 2007-2-28 18:35 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

/**
 * 实现iterator以使遍历容器和容器的实现相分离.
 *
 */
class Collection implements Iterator {
  private $arr;
  private $index;
  function __construct(){
    $this->arr=array();
    $this->index=0;
  }
  function add($mix){
    $this->arr[]=$mix;
  }

  //实现iterator接口的方法,使此类可以成为foreach的参数
  function current(){
    return current($this->arr);
  }

  function next(){
    $this->index++;
    return next($this->arr);
  }

  function key(){
    return key($this->arr);
  }

  function valid(){
    return $this->index < count($this->arr);
  }

  function rewind(){
    $this->index=0;
    reset($this->arr);
  }
}
echo '<pre>';

$col=new Collection();
$col->add('one');
$col->add('two');
$col->add('three');

foreach ($col as $value) {
    echo "$value\n";
}

foreach ($col as $value) {
    echo "$value\n";
}
?>

[ 本帖最后由 书生 于 2007-2-28 18:36 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

class Context {
  private $words;
  private $index;
  private $len;
  private $currentWord;

  function __construct($expr){
    $sub=array();
    $expr=preg_replace('/\s/','',$expr);
    preg_match_all('/([\d]+)|(\+)|(\-)|(\*)|(\/)|(\()|(\))/',$expr,$sub);
    $this->words=$sub[0];
    if (!$this->words) {
        throw new Exception("非法表达式");
    }
    $this->len=count($this->words);
    $this->index=0;
    $this->currentWord=null;
    $this->nextWord();
  }

  /**
   * @return string
   */
  function nextWord(){
    if ($this->index<$this->len) {
        $this->currentWord=$this->words[$this->index++];
    }else {
        $this->currentWord=null;
    }
    return $this->currentWord;
  }

  /**
   * @return string
   */
  function currentWord(){
    return $this->currentWord;
  }
}

interface Expr {
  /**
   * @param Context $ctx
   * @return int
   */
  function interpret(Context $ctx);
}

class NumberExpr implements Expr {
  /**
   * @param Context $ctx
   * @return int
   */
  function interpret(Context $ctx){
    $left=$ctx->currentWord();
    if ($left=='(') {
        $expr=new BracketExpr();
        return $expr->interpret($ctx);
    }
    $left=intval($left);
    $word=$ctx->nextWord();
    if ($word!==null) {
        switch ($word) {
            case '+':
            case '-':
            $expr=new AddExpr($left);
          return $expr->interpret($ctx);
            default:
                throw new Exception("unknow operator after $left");
        }
    }
    return $left;
  }
}

class AddExpr implements Expr {
  private $left;
  /**
   * @param int $left
   */
  function __construct($left){
    $this->left=$left;
  }
  /**
   * @param Context $ctx
   * @return int
   */
  function interpret(Context $ctx){
    $oper=$ctx->currentWord();
    $right=$ctx->nextWord();
    if ($right===null) {
        throw new Exception("nothing after operator $oper");
    }
    switch ($oper) {
        case '+':
            $this->left+=$right;
        break;
        case '-':
          $this->left-=$right;
        break;
        default:
            throw new Exception("unknow operator $oper");
    }
    $oper=$ctx->nextWord();
    if ($oper!==null) {
        return $this->interpret($ctx);
    }else {
        return $this->left;
    }
  }
}

if (isset($_GET['expr'])) {
    $exp=$_GET['expr'];
  echo '<pre>';
  $ctx=new Context($exp);
  $expr=new NumberExpr();
  echo $exp,'=',$expr->interpret($ctx),'<br />';
}
?>
<form method="get" action="<?php $_SERVER['REQUEST_URI'] ?>">
  <input type="text" name="expr" />
  <input type="submit" value="eval"/>
</form>
[ 本帖最后由 书生 于 2007-3-1 08:53 编辑 ]

作者: 书生   发布时间: 2007-02-25

复制PHP内容到剪贴板
PHP代码:

<?php

final class Immutable {

  private $value;

  function __construct($value){
    $this->value=$value;
  }

  function getValue(){
    return $this->value;
  }
}

//不变模式为多线程模式,通常与享元模式一起共用.
//由于php脚本处理只有单线程,所以不变模式通常没什么用
?>

作者: 书生   发布时间: 2007-03-01

GOOD,为每一模式加一个简单的概念性的说明就更好..

作者: 一地风飞   发布时间: 2007-03-01

好贴

作者: fengyun   发布时间: 2007-03-01

引用:
原帖由 一地风飞 于 2007-3-1 09:24 发表
GOOD,为每一模式加一个简单的概念性的说明就更好..
太匆忙了.会慢慢加的.

作者: 书生   发布时间: 2007-03-01

FACTORY―人才市场:以往是要哪个人才,就找哪个人才,效率低,现在有了人才市场,我们只需
直接去人才市场挑一个好了;

BUILDER―生产流水线:以前是手工业作坊式的人工单个单个的生产零件然后一步一步组装做,好
比有了工业革命,现在都由生产流水线代替了。如要造丰田汽车,先制定汽车的构造如由车胎、方
向盘、发动机组成。再以此构造标准生产丰田汽车的车胎、方向盘、发动机。然后进行组装。最后
得到丰田汽车;

PROTOTYPE―印刷术的发明:以前只能临贴才能保持和别人的字迹基本相同,直从印刷技术发明,
从而保证了复制得和原物一模一样;

SINGLETON―唯一:以前是商标满天飞,相同的商标难免造成侵权,直从有商标保护法后,就保证
了不会再产生第家企业使用相同的商标;
结构型模式

ADAPTER―集众人之私,成一己之公:武当派张三丰会太极拳,少林派智空大师会金刚般若掌,如
果他们两个都成为我的师傅,我就既会太极拳,又会金刚般若掌了;

DECORATOR―青出于蓝而胜于蓝:武当派张三丰会太极拳,是我师傅,他教会了我太极拳,但我自
己还会点蒙古式摔交,张三丰却不会。于是我就成了DECORATOR模式的实现;

BRIDGE―白马非马:马之颜色有黑白,马之性别有公母。我们说”这是马”太抽象,说”这是黑色
的公马”又太死板,只有将颜色与性别和马动态组合,”这是(黑色的或白色的)(公或母)马”
才显得灵活而飘逸,如此bridge模式精髓得矣。

COMPOSITE―大家族:子又生孙,孙又生子,子子孙孙,无穷尽也,将众多纷杂的人口组织成一个
按辈分排列的大家族即是此模式的实现;

FACADE―求同存异:高中毕业需读初中和高中,博士也需读初中和高中,因此国家将初中和高中普
及成九年制义务教育;

FLYWEIGHT―一劳永逸:认识三千汉字,可以应付日常读书与写字,可见头脑中存在这个汉字库的
重要;

PROXY―垂帘听政:犹如清朝康熙年间的四大府臣,很多权利不在皇帝手里,必须通过辅佐大臣去
办;


行为模式

CHAIN OF RESPONSIBLEITY―租房:以前为了找房到处打听,效率低且找不到好的房源。现在有了
房屋中介,于是向房屋中介提出租房请求,中介提供一个合适的房源,满意则不再请求,不满意
继续看房,直到满意为止;

COMMAND―借刀杀人:以前是想杀谁就杀,但一段时间后领悟到,长此以往必将结仇太多,于是假
手他人,挑拨他人之间的关系从而达到自己的目的;

INTERPRETER―文言文注释:一段文言文,将它翻译成白话文;

ITERATOR―赶尽杀绝:一个一个的搜索,绝不放掉一个;

MEDIATOR―三角债:本来千头万绪的债务关系,忽出来一中介,包揽其一切,于是三角关系变成了
独立的三方找第四方中介的关系;

MEMENTO―有福同享:我有多少,你就有多少;

OBSERVER―看守者:一旦被看守者有什么异常情况,定会及时做出反应;

STATE―进出自由:如一扇门,能进能出,如果有很多人随时进进出出必定显得杂乱而安全,如今
设一保安限制其进出,如此各人进出才显得规范;

STRATEGY―久病成良医:如人生病可以有各种症状,但经过长期摸索,就可以总结出感冒、肺病、
肝炎等几种;


TEMPLATE METHOD――理论不一定要实践:教练的学生会游泳就行了,至于教练会不会则无关紧要;

VISITOR―依法治罪:因张三杀人要被处死,李四偷窃要被罚款。由此势必制定处罚制度,故制定
法律写明杀人、放火、偷窃等罪要受什么处罚,经通过后须变动要小。今后有人犯罪不管是谁,按
共条例处罚即是,这就是访问者模式诞生的全过程;  

转自:
http://www.matrix.org.cn/resource/article/2005-06-09/1624.html

作者: 书生   发布时间: 2007-03-01

好贴子 谢谢楼主

作者: 影子的影子   发布时间: 2007-03-02

好帖子~~~~
有好多要好好看看才能明白。。。。。。谢谢楼主了!!!!!

作者: hackshel   发布时间: 2007-03-02

还需要慢慢品尝

作者: 特蓝克斯   发布时间: 2007-03-02

好帖要顶 :)

书生兄弟其实可以做个PDF小手册,把这些代码收集起来,加上简单的注解,定期维护,还是挺不错的~

作者: Verdana   发布时间: 2007-03-06

书生 (百无一用)

银牌大侠




   
UID 13676
精华 0
积分 2771
帖子 989
威望 2089
阅读权限 50
注册 2006-10-28
状态 离线  


这么好的帖子还不置精??????

应该放在 phpchina 的大门晒几天才对.......

作者: 小陈   发布时间: 2007-03-11

文字介绍太少了
应该把那个GOF的<设计模式>代码部分用PHP实现,然后发上来就好了.

作者: 玉面修罗   发布时间: 2007-03-11

惭愧
GOF的是C++,看不懂,
文字介绍正在整理总体部分,参考了很多,把自己的头都搞晕了.

[ 本帖最后由 书生 于 2007-3-12 09:54 编辑 ]

作者: 书生   发布时间: 2007-03-12

现在太忙了,如果以后时间和技术允许的话,我会把我认为几本经典的面向对象设计原则和设计模式的书代码部分用PHP重写。那相信很多PHPER都愿意看了。

作者: 玉面修罗   发布时间: 2007-03-12

这么好的东西我怎么才看到

作者: sunjian   发布时间: 2007-07-19

太无敌了吧,那时候一看到模式就头疼。

作者: kobejiang   发布时间: 2007-07-26

好东西,建议整理成电子书,没事了就翻翻

作者: Moonfly   发布时间: 2007-07-28

好东西,一会研究一下.

作者: xydream   发布时间: 2008-01-20

热门下载

更多