www.2527.com_澳门新葡8455手机版_新京葡娱乐场网址_
做最好的网站

PHP设计情势之命令形式的尖锐深入分析_php本事

2019-11-24 02:18 来源:未知

例如,《设计模式》一书推荐使用Command存储用户行为链,以支持撤销和重做操作。

 代码如下

解释器模式旨在为一个简单的抽象表达式方法实现利用复合分层结构,解释器操作的参数通常统称为上下文,对于给定的一个方法,它们通常被计算值代替,或它们对某些操作可能不存在。

注意PHP 5.3函数编程能力可以被当做Command模式的一个本地实现,但为每一个命令层次结构使用抽象数据类型有助于类型安全。

1.保护值对象的属性,禁止被直接访问。

同样,当包含一个解释器时,复合模式的叶子和容器参与者名称会不一样,这些名称反映了它们所扮演的角色:终结符或非终结符表达式。

如果你熟悉C或PHP,你可能已经遇到过Command,它相当于程序中的:回调。回调通常使用一个函数指针或数据结构如PHP中的字符串和数组实现,Command是在一个方法调用之上的抽象,它吸收了所有面向对象的好处:合成、继承和处理。

 代码如下

参与者:◆客户端:使用解释操作。◆抽象表达式:基于一个表达式树抽象。◆非终结符表达式(NonTerminalExpression):递归地包含其它抽象表达式的表达式。◆终结符表达式:不能够进一步简化的表达式。《设计模式》一书针对这个模式提供了一个扩展示例,我将使用数学表达式替换布尔表达式重新改造了一下,因此这个例子解决了一个数学表达式的展现,它的evaluate被分离在一个不同的ConcreteExpression类中。复制代码 代码如下:/** * AbstractExpression. All implementations of this interface * are ConcreteExpressions. */ interface MathExpression { /** * Calculates the value assumed by the expression. * Note that $values is passed to all expression but it * is used by Variable only. This is required to abstract * away the tree structure. */ public function evaluate; } /** * A terminal expression which is a literal value. */ class Literal implements MathExpression { private $_value; public function __construct { $this->_value = $value; } public function evaluate { return $this->_value; } } /** * A terminal expression which represents a variable. */ class Variable implements MathExpression { private $_letter; public function __construct { $this->_letter = $letter; } public function evaluate { return $values[$this->_letter]; } } /** * Nonterminal expression. */ class Sum implements MathExpression { private $_a; private $_b; public function __construct(MathExpression $a, MathExpression $b) { $this->_a = $a; $this->_b = $b; } public function evaluate { return $this->_a->evaluate $this->_b->evaluate; } } /** * Nonterminal expression. */ class Product implements MathExpression { private $_a; private $_b; public function __construct(MathExpression $a, MathExpression $b) { $this->_a = $a; $this->_b = $b; } public function evaluate { return $this->_a->evaluate * $this->_b->evaluate; } } // 10 $expression = new Product, new Sum, new Literal; echo $expression->evaluate, "n"; // adding new rules to the grammar is easy: // e.g. Power, Subtraction... // thanks to the Composite, manipulation is even simpler: // we could add substitute($letter, MathExpression $expr) // to the interface...

在这个模式中,Invoker知道传递给它的Command,无需依赖于真实的ConcreteCommand实现,解决了通过配置进行方法调用相关的问题,如UI控件按钮和菜单等引用一个Command,它们的行为是通过通用的ConcreteCommand实例呈现的。参与者:◆Command:在一个方法调用之上定义一个抽象;◆ConcreteCommand:一个操作的实现;◆Invoker:引用Command实例作为它可用的操作。下面的代码展示了Validator组件作为Command对象实现的示例:复制代码 代码如下:/** * The Command abstraction. * In this case the implementation must return a result, * sometimes it only has side effects. */ interface Validator { /** * The method could have any parameters. * @param mixed * @return boolean */ public function isValid; } /** * ConcreteCommand. */ class MoreThanZeroValidator implements Validator { public function isValid { return $value > 0; } } /** * ConcreteCommand. */ class EvenValidator implements Validator { public function isValid { return $value % 2 == 0; } } /** * The Invoker. An implementation could store more than one * Validator if needed. */ class ArrayProcessor { protected $_rule; public function __construct { $this->_rule = $rule; } public function process { foreach { if ($this->_rule->IsValid { echo $n, "n"; } } } } // Client code $processor = new ArrayProcessor; $processor->process(array(1, 20, 18, 5, 0, 31, 42)); 使用PHP设计模式中的命令模式的一些注意事项:◆方法调用中的某些参数可以在构造ConcreteCommand时提供,有效地局部套用原始函数;◆一个Command可以被看作是一个非常简单的只有一个方法的策略,重点放在对象的操作上;◆ConcreteCommands也要组织它们需要的每一个资源,以实现它们的目标,主要是行为的Receiver,它们调用方法执行一个Command;◆复合模式,装饰模式和其它模式都可以和命令模式组合,获得更多的Command,装饰Command等等。

 代码如下

树是一个抽象的名词,因为实际上大多数时候它是一个表达式的抽象表现,它忽略了可能有一个字符串,也可能有一个数据结构的具体表达式,(例如,在PHP中,“A”和“x41”是相同抽象字面值的不同具体表现),通过逻辑规则解耦结果,使解释过程大大简化。

命令模式,命令模式是封装一个通用操作的机制。

再说设计模式-值对象模式之前,你要了解值传递和引用传递:

解释器模式,它包括一个具有复合类分层结构的文法表现,规则是映射到类,跟随在文法后面的表达式可以被转换成一个抽象的语法树,除了复合模式的实例对象图外,没有别的内容。

看上面例子,可以知道明显的错误是$p1和$p2使用的是同一个BadDollar对象,首先,类Work和类Person的实例已经创建。那么,假设每一个雇员最初有一个空的电子钱包,雇员的电子钱包Person:wallet是通过Work::payDay()函数返回的对象资源变量赋值的,所以被设定为一个BadDollar类的对象实例。实际上,$job::salary,、$p1::wallet和$p2::wallet指向的是同一个对象的实例。
使用值对象模式,重新设计Dollar对象如下

解释器不是一个很常见的模式,但对于简单的语法,它添加一个规则就象添加一个类那样容易,但它没有解决从具体表现形式到抽象语法树的转换,这是由其它服务完成的。

<?php

<?php

/**
* 定义观察接口
*/
interface Subject
{
    public function Attach($Observer); //添加观察者
    public function Detach($Observer); //踢出观察者
    public function Notify(); //满足条件时通知观察者
    public function SubjectState($Subject); //观察条件
}
 
/**
* 观察类的具体实现
*/
class Boss Implements Subject
{
    public $_action;
   
    private $_Observer;
   
    public function Attach($Observer)
    {
        $this->_Observer[] = $Observer;
    }
   
    public function Detach($Observer)
    {
        $ObserverKey = array_search($Observer, $this->_Observer);
       
        if($ObserverKey !== false)
        {
            unset($this->_Observer[$ObserverKey]);
        }
    }
   
    public function Notify()
    {
        foreach($this->_Observer as $value )
        {
            $value->Update();
        }
    }
   
    public function SubjectState($Subject)
    {
        $this->_action = $Subject;
    }
}
 
/**
* 抽象观察者
*
*/
abstract class Observer
{
    protected $_UserName;
   
    protected $_Sub;
   
    public function __construct($Name,$Sub)
    {
        $this->_UserName = $Name;
        $this->_Sub = $Sub;
    }
   
    public abstract function Update(); //接收通过方法
}
 
/**
* 观察者
*/
class StockObserver extends Observer
{
    public function __construct($name,$sub)
    {
        parent::__construct($name,$sub);
    }
   
    public function Update()
    {
        echo $this->_Sub->_action.$this->_UserName." 你赶快跑...";
    }
}
 
$huhansan = new Boss(); //被观察者
 
$gongshil = new StockObserver("三毛",$huhansan); //初始化观察者
 
$huhansan->Attach($gongshil); //添加一个观察者
$huhansan->Attach($gongshil); //添加一个相同的观察者
$huhansan->Detach($gongshil); //踢出基中一个观察者
 
$huhansan->SubjectState("警察来了"); //达到满足的条件
 
$huhansan->Notify(); //通过所有有效的观察者

 代码如下

2.摘自PHPCHINA的一个不错例子:

可以看到,主要的变化在于Dollar:add()函数中,它是创建并返回一个新的Dollar实例,所以,尽管你指定当前对象给多个变量,但是每一个变量的变化都不会影响其它的变量实例。
值对象模式设计注意:

 代码如下

三、命令模式

一、值对象模式

二、策略模式

//观察者
interface IObserver
{
 public function notify();
}
 
//定义可以被观察的对象接口
interface IObservable
{
 public function addObserver($observer);
}
 
//实现IObservable接口
class MessageSystem Implements IObservable
{
 private $_observers = array();
 
 public function addObserver($observer)
 {
  $this->_observers = $observer;
 }
 
 public function doNotify()
 {
  foreach($this->_observers as $o)
  {
   $o->notify();
  }
 }
}
 
//实现IObserver接口
class User Implements IObserver
{
 public function __construct($username)
 {
  echo "我是新用户{$username}<br/>";
 }
 //通知观察者方法
 public function notify()
 {
  echo '欢迎新用户';
 }
}
 
//使用
$u = new MessageSystem();
 
$u->addObserver(new User('小明'));
//$u->addObserver(new User('小红'));
//$u->addObserver(new User('小黑'));
 
$u->doNotify();

1.策略模式概念 策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,此模式让算法的变化独立于使用算法的客户。从而让程序结构更灵活,具有更好的扩展性和维护性
2.策略模式结构图

1.命令模式概念:
将来自客户端的请求传入一个对象,从而使你可用不同的请求对客户进行参数化。用于“行为请求者”与“行为实现者”解耦,可实现二者之间的松耦合,以便适应变化。 
2.参与者:

<?php
 
class BadDollar {
  protected $amount;
 
  public function __construct($amount=0) {
    $this->amount = (float)$amount;
  }
 
  public function getAmount() {
    return $this->amount;
  }
 
  public function add($dollar) {
    $this->amount = $dollar->getAmount();
  }
}
 
class Work {
  protected $salary;
 
  public function __construct() {
    $this->salary = new BadDollar(200);
  }
 
  public function payDay() {
    return $this->salary;
  }
 
}
 
class Person {
  public $wallet;
}
 
 
$job = new Work;
$p1 = new Person;
$p2 = new Person;
$p1->wallet = $job->payDay();
print_r($p1->wallet->getAmount()); //200
 
$p2->wallet = $job->payDay();
print_r($p2->wallet->getAmount()); //200
 
$p1->wallet->add($job->payDay());
print_r($p1->wallet->getAmount()); //400
 
//this is bad — actually 400
print_r($p2->wallet->getAmount()); //400
 
//this is really bad — actually 400
print_r($job->payDay()->getAmount()); //400

在这个模式中,Invoker(调用者)知道传递给它的Command,无需依赖于真实的ConcreteCommand(具体的命令)实现,解决了通过配置进行方法调用相关的问题,如UI控件按钮和菜单等引用一个Command,它们的行为是通过通用的ConcreteCommand实例呈现的。

 

 

2.在构造函数中就对属性进行赋值。

首先了解观察者模式的概念:一个对象通过添加一个方法(该方法允许另一个对象,即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。观察者模式是一种事件系统,意味着这一模式允许某个类观察另一个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作;观察者模式为您提供了避免组件之间紧密耦。看下面例子你就明白了!
1.使用观察者模式实现消息推送

3.策略模式角色说明
    抽象策略(Strategy)角色:定义所有支持的算法的公共接口。通常是以一个接口或抽象来实现。Context使用这个接口来调用其ConcreteStrategy定义的算法。
    具体策略(ConcreteStrategy)角色:以Strategy接口实现某具体算法
    环境(Context)角色:持有一个Strategy类的引用,用一个ConcreteStrategy对象来配置
4.策略模式实例 
比如说购物车系统,在给商品计算总价的时候,普通会员肯定是商品单价乘以数量,但是对中级会员提供8者折扣,对高级会员提供7折折扣,这种场景就可以使用策略模式实现:

四、观察者模式

3.去掉任何一个会改变属性值的方式函数(setter),否则属性值很容易被改变

class Dollar {
  protected $amount;
 
  public function __construct($amount=0) {
    $this->amount = (float)$amount;
  }
 
  public function getAmount() {
    return $this->amount;
  }
 
  public function add($dollar) {
    return new Dollar($this->amount $dollar->getAmount());
  }
}

//抽象策略角色《为接口或者抽象类,给具体策略类继承》
interface Strategy
{
    public function computePrice($price);
}
 
//具体策略角色-普通会员策略类
class GenernalMember implements Strategy
{
    public function computePrice($price)
    {
        return $price;
    }
}
 
//具体策略角色-中级会员策略类
class MiddleMember implements Strategy
{
    public function computePrice($price)
    {
        return $price * 0.8;
    }
}
 
//具体策略角色-高级会员策略类
class HignMember implements Strategy
{
    public function computePrice($price)
    {
        return $price * 0.7;
    }
}
 
//环境角色实现类
class Price
{
    //具体策略对象
    private $strategyInstance;
   
    //构造函数
    public function __construct($instance)
    {
        $this->strategyInstance = $instance;
    }
   
    public function compute($price)
    {
        return $this->strategyInstance->computePrice($price);
    }
}
 
//客户端使用
$p = new Price(new HignMember());
 
$totalPrice = $p->compute(100);
 
echo $totalPrice; //70

图片 1

<?php
//命令
interface Validator 

    /** 
     * The method could have any parameters. 
     * @param mixed 
     * @return boolean 
     */
    public function isValid($value); 

 
//具体命令
class MoreThanZeroValidator implements Validator 

    public function isValid($value) 
    { 
        return $value > 0; 
    } 

 
//具体命令
class EvenValidator implements Validator 

    public function isValid($value) 
    { 
        return $value % 2 == 0; 
    } 

 
//调用者
class ArrayProcessor 

    protected $_rule; 
 
    public function __construct (Validator $rule) 
    { 
        $this->_rule = $rule; 
    } 
 
    public function process(array $numbers) 
    { 
        foreach ($numbers as $n) { 
            if ($this->_rule->IsValid($n)) { 
                echo $n, " "; 
            } 
        } 
    } 

 
//客户端
$processor = new ArrayProcessor(new EvenValidator()); 
$processor->process(array(1, 20, 18, 5, 0, 31, 42));

图片 2
1.值对象模式概念:
如果你把同一个对象资源赋值给两个不同的变量,然后改变其中的一个变量,另一个变量仍然不受影响。这就是使用值对象模式的目的。
看下面例子:

  • Command(命令):在一个方法调用之上定义一个抽象;
  • ConcreteCommand(具体的命令):一个操作的实现;
  • Invoker(调用者):引用Command实例作为它可用的操作。
TAG标签:
版权声明:本文由澳门新葡8455手机版发布于计算机编程,转载请注明出处:PHP设计情势之命令形式的尖锐深入分析_php本事