1

私はいくつかのクラスを書き、私が何をすべきかについて道の分岐点に来ました。私の基本的な質問は、非常によく似た機能を持つクラス間でコードが重複しないようにするにはどうすればよいですか?特性は今のところ私にとって選択肢ではありません、そして私はそれらがとにかくここであまり役に立たないと思います。

次のクラスを実装しています。


    //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{}

これらのクラスは、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ファイルオブジェクトを作成したいということです。ほとんどすべてのファイル/ディレクトリをロックできるようにしたいのですが、複製する必要はありません。コード。次のうちどれをすべきですか



    //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がこれのすべて/ほとんどを実行する」と言う人もいると思います。例としてここにメソッドを含めましたが、実装したすべてのメソッドがここにあるわけではないため、これが私が作成した機能だけではありません。ただし、この問題全体を回避する設計にたどり着く可能性があるため、これらすべてのコメントなどを歓迎します。

ありがとうございました

4

2 に答える 2

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);
    }
}
于 2012-03-05T22:55:35.950 に答える
0

Strategyパターンを調べるべきだと思います。それを継承しようとするのではなく、ロック可能性戦略の構成を使用することを検討してください。

于 2012-03-05T22:32:43.607 に答える