2012-03-05 53 views
1

我已經寫了幾個類,並且在我應該做什麼的道路上來到了一個分支。我的基本問題是,如何避免在具有非常類似功能的類中複製我的代碼?目前,性狀對我來說不是一種選擇,我不認爲他們會在這裏幫助太多。PHP類建模問題

我有以下類實現。

 

    //either a directory or a file on the file system 
    class FileSystem_Object{ 
     //the size of the class in bytes 
     public function getSize(){} 

     //same as phps native realpath 
     public function getRealPath(){} 
    } 

    //a zip file on the file system, e.g. files that end in .zip extension. 
    class FileSystem_Object_Zip extends FileSystem_Object{ 
     //returns size of all files if they were to be uncompressed, in bytes 
     public function getUncompressedSize(){} 
    } 

    //a singleton file that keeps track of only one object copy of a file 
    class FileSystem_Manager{} 
 

這些類sortof我提供一些SPLFileObject類型的功能。我可以做以下這種東西

 

    $object = 
     FileSystem_Manager::getInstance() 
     ->getFileSystemObjecT('/some/path/to/file/or/directory/'); 

 

我每次調用getFileSystemObject方法它要麼返回一個新的類對象或返回被分配到該路徑已經是一個對象,從而避免了我創建多個對象點到文件系統上的相同路徑。 (也許不是最好的主意,但這就是我的意圖。)

下面是我們遇到問題的地方。

我有另一套我用來'鎖定'對象的類。現在,我鎖定的唯一對象是filesystem_objects,無論它們是目錄還是文件。這足以通過基於php進程的進程ID試圖鎖定文件來創建文件的鎖定文件。

 


    inteface Lockable_Object{ 

     public functon getLockableIdentifier(); 
    } 

    class Lockable_FileSystemObject implements Lockable_Object{ 

     /** 
     * I return a false here if the file doesn't exist 
     * so any other processes trying to lock this file will 
     * know they can no longer lock it because it has moved 
     * or been renamed for some reason. 
     */ 

     public functon getLockableIdentifier(){ 
      if(file_exists($this->_fullFilePath)){ 
       return $this->getRealPath(); 
      } 
      return false; 
     } 
    } 

 

我現在面臨的問題是,我想創建一個可以被鎖定,以及一個Zip文件對象,我希望能夠鎖定幾乎任何文件/目錄,但我不'T想要重複代碼。以下哪我應該做的

 


    //Option 1 
    class Lockable_Object_Zip extends FileSystem_Object_Zip 
           implements Lockable_Object{ 
     //In here I would have to duplicate the getLockableIdentifier method and do that 
     //for every file type i decide to make in the future 
    } 

    //Option 2 
    class Lockable_Object_Zip extends Lockable_FileSystemObject 
     //In here I would have to duplicate all the zip functionality coded into 
     //FileSystem_Object_Zip 
    } 

    //Option 3 
    class FileSystem_Object implements Lockable_Object{ 
     //build in the 'lockablity' into the base class 
    } 

 

現在我傾向於選擇3,但唯一的原因,我不喜歡這樣做,是因爲那時我就必須有我的圖書館「洛克」部分每當我想使用文件系統的東西;它會更緊密地耦合在一起。

我相信你會對設計發表評論,有人會說「SplFileObject可以完成所有這些工作」。我在這裏包含了一些方法的示例,並不是我實現的所有方法都在這裏,所以這不是我寫的唯一功能。然而,所有這些意見和更多都是值得歡迎的,因爲它們可能會讓我陷入一種可以避免這個問題的設計中。

謝謝

+0

你可能想看看'SplFileObject','ZipArchive','FileSystemIterator'和'DirectoryIterator'你繼續有推倒重來之前; ) – Gordon 2012-03-05 22:30:06

+0

@戈登,注意到了,但我看過那些。你會如何建議我做文件鎖定呢?或者添加zip文件的特定功能,以便輕鬆訪問未壓縮的大小?迭代器和我可以使用的所有東西,但是當涉及到使用一種特定的文件類型時,我仍然需要做更多的編碼。 – 2012-03-05 22:37:09

回答

0

如果鎖定類的類型並不重要,你可以用Decorator模式,例如去

class Lockable 
{ 
    protected $lockable; 

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

    public function lock() 
    { 
     // .. your code to lock $this->lockable 
    } 

    public function __call($method, $args) 
    { 
     return call_user_func_array(array($this->lockable, $method), $args); 
    } 
} 

這樣你就不會重複邏輯。缺點是不能使用的方法裝飾的情況下,要求裝飾類型(除非你添加相應的接口和委託所有調用)。

策略模式將是另一種選擇:

class LockingStrategy 
{ 
    public function lock($fileSystemObject) 
    { 
     // your code to lock $fileSystemObject 
    } 
} 

class ZipFile 
… 
    public function __construct(LockingStrategy $strategy) 
    { 
     $this->lockingStrategy = $strategy; 
    } 
    public function lock() 
    { 
     $this->lockingStrategy->lock($this); 
    } 
} 
+0

是的,我喜歡裝飾模式,這聽起來像一個很好的方式去。我原本想寫一個'set'的鎖定類,每個'知道'如何鎖定某種類型的對象。感謝Gordon的幫助。這將幫助我不復制文件功能。更方便。 – 2012-03-06 03:56:36

0

我想你應該看看戰略模式。考慮使用Lockable策略的組合,而不是試圖繼承它。