ビジター デザイン パターンはいつ使用すればよいですか? [closed] 質問する

ビジター デザイン パターンはいつ使用すればよいですか? [closed] 質問する

ブログでビジターパターンについて言及されているのをよく見かけますが、正直言って私には理解できません。パターンに関するWikipediaの記事その仕組みは理解していますが、いつ使用すればよいのかまだわかりません。

最近デコレータ パターンを理解し、あらゆる場所でその使用法を目にするようになった私としては、この一見便利なパターンも直感的に理解できるようになりたいです。

ベストアンサー1

私はビジターパターンにあまり詳しくありません。正しく理解できたかどうか確認してみましょう。動物の階層があるとします

class Animal {  };
class Dog: public Animal {  };
class Cat: public Animal {  };

(インターフェースが確立された複雑な階層であると仮定します。)

ここで、階層に新しい操作を追加して、各動物に音を鳴らしてもらいます。階層がこのように単純な場合は、単純なポリモーフィズムで実行できます。

class Animal
{ public: virtual void makeSound() = 0; };

class Dog : public Animal
{ public: void makeSound(); };

void Dog::makeSound()
{ std::cout << "woof!\n"; }

class Cat : public Animal
{ public: void makeSound(); };

void Cat::makeSound()
{ std::cout << "meow!\n"; }

しかし、この方法で進めると、操作を追加するたびに、階層のすべてのクラスへのインターフェイスを変更する必要があります。ここで、元のインターフェイスに満足しており、それに対する変更をできるだけ少なくしたいとします。

ビジターパターンでは、新しい操作を適切なクラスに移動することができ、階層のインターフェースを一度だけ拡張するだけで済みます。やってみましょう。まず、抽象操作(「Visitor」クラス)を定義します。ゴーフ) には、階層内のすべてのクラスに対応するメソッドがあります。

class Operation
{
public:
    virtual void hereIsADog(Dog *d) = 0;
    virtual void hereIsACat(Cat *c) = 0;
};

次に、新しい操作を受け入れるために階層を変更します。

class Animal
{ public: virtual void letsDo(Operation *v) = 0; };

class Dog : public Animal
{ public: void letsDo(Operation *v); };

void Dog::letsDo(Operation *v)
{ v->hereIsADog(this); }

class Cat : public Animal
{ public: void letsDo(Operation *v); };

void Cat::letsDo(Operation *v)
{ v->hereIsACat(this); }

最後に、 Cat も Dog も変更せずに実際の操作を実装します。

class Sound : public Operation
{
public:
    void hereIsADog(Dog *d);
    void hereIsACat(Cat *c);
};

void Sound::hereIsADog(Dog *d)
{ std::cout << "woof!\n"; }

void Sound::hereIsACat(Cat *c)
{ std::cout << "meow!\n"; }

これで、階層を変更せずに操作を追加できるようになりました。仕組みは次のとおりです。

int main()
{
    Cat c;
    Sound theSound;
    c.letsDo(&theSound);
}

おすすめ記事