依赖注入和工作单元模式

时间:2010-06-10 08:06:30

标签: php dependency-injection

我陷入两难境地。我使用DI(读取:工厂)为自制ORM提供核心组件。 容器根据请求提供数据库连接,DAO,Mappers及其生成的域对象。

以下是Mappers和Domain Object类的基本概要

class Mapper{
    public function __constructor($DAO){
        $this->DAO = $DAO;
        }

    public function load($id){
        if(isset(Monitor::members[$id]){
        return Monitor::members[$id];

        $values = $this->DAO->selectStmt($id);
        //field mapping process omitted for brevity
        $Object = new Object($values);
        return $Object;
        }
    }

 class User(){
     public function setName($string){
        $this->name = $string;
        //mark modified by means fair or foul
     }
 }

ORM还包含一个基于工作单元模式的类(Monitor),即

class Monitor(){
    private static array modified;
    private static array dirty;
    public function markClean($class);
    public function markModified($class);
}

ORM类本身只是协调从DI容器中提取的资源。因此,要实例化一个新的User对象:

$Container = new DI_Container;
$ORM = new ORM($Container);
$User = $ORM->load('user',1);
//at this point the container instantiates a mapper class
//and passes a database connection to it via the constructor
//the mapper then takes the second argument and loads the user with that id
$User->setName('Rumpelstiltskin');//at this point, User must mark itself as "modified"

我的问题是这个。当用户在Domain Object类上设置值时,我需要在Monitor类中将该类标记为“脏”。我有三个选项之一,我可以看到它

1:将Monitor类的实例传递给Domain Object。我注意到这在FirePHP中被标记为递归 - 即     $这 - >监视器 - > markModified($此)

2:直接在域对象中实例化监视器 - 这会破坏DI吗? 3:使Monitor方法保持静态,并从域对象内部调用它们 - 这会破坏DI也不是吗?

你推荐的行动方案是什么(除了使用现有的ORM,我这样做是为了好玩......)

3 个答案:

答案 0 :(得分:1)

好的,我明白了。那怎么样:

 $user = new User;
 $monitoredUser = new Monitor( $user );

 //at update in class Monitor:
 Monitor::markDirty( $this );

现在您将Monitor用作装饰器;它在用户对象或处理传入请求的任何其他对象周围添加了一个shell。如果一个对象得到更新,它将被监视器标记为脏,但是因为Monitor使用静态方法,所以它保持在当前类范围内,从而避免了递归。

答案 1 :(得分:0)

以为我从来没有这样做,你的Monitor类似乎对应于“观察者”设计模式。这样您就不必要求Monitor类将类标记为脏,但它应该单独执行。

正如我所说,我从来没有在PHP中做到这一点,但我非常有信心你可以在谷歌上看一种在PHP中实现这种设计模式的方法。

答案 2 :(得分:0)

很大的问题是; markModified()中发生了什么?我复制到代码并尝试了,但我没有收到您报告的错误。所以我猜想丢失了一块拼图?