【GoFのデザインパターン】行動パターン:Visitorパターン

当サイトではアフィリエイト広告を利用しています。

GoF

Visitorパターンの必要性と使用しない場合の問題点

教授:「Visitorパターンは、オブジェクト構造の要素に対して操作を行うことができるデザインパターンだよ。まずは、Visitorパターンがなぜ必要なのかを理解しよう。」

生徒:「はい、でもなぜそのようなパターンが必要なんですか?」

Visitorパターンの必要性

教授:「考えてみて。あるオブジェクト構造に対して様々な操作を頻繁に追加したい場合がある。でも、その構造自体を変更することなく、どうやって新しい操作を容易に追加できるだろう?」

生徒:「うーん、それは難しそうですね。構造を変えずに新しい機能を…。」

教授:「そこでVisitorパターンの出番だよ。このパターンを使えば、オブジェクトの構造を変更することなく、新たな操作を追加できるんだ。」

使用しない場合の問題点

生徒:「Visitorパターンを使わなかったら、どうなるんですか?」

教授:「いい質問だね。Visitorパターンを使わない場合、新しい操作を追加するたびに、オブジェクト構造を構成するクラスを修正する必要がある。これは、構造が頻繁に変わる場合や多くの異なる操作をサポートする必要がある場合に、特に問題となる。」

生徒:「なるほど、構造を変えずに済むのは大きなメリットですね。でも、Visitorパターンにはどんなデメリットがあるんですか?」

教授:「Visitorパターンは、オブジェクト構造の各要素とVisitor間の結合を強めることになるから、構造が固定されていて変更が少ない場合には、その利点を享受しにくいかもしれないね。」

生徒:「理解しました!Visitorパターンは、新しい操作を頻繁に追加する必要があるが、構造を変えたくない場合に役立つんですね。」

教授:「その通り!良く理解できたね。」

Visitorパターン入門

この記事では、デザインパターンの一つであるVisitorパターンについて説明します。Visitorパターンを用いることで、オブジェクトの構造に変更を加えることなく、新たな操作を容易に追加することができます。

Visitorパターンとは?

Visitorパターンは、操作をオブジェクト構造から分離して、新しい操作を追加したい時に有効なデザインパターンです。これにより、オブジェクト構造を変更することなく新しい操作を追加することが可能になります。

Visitorパターンのサンプルコード(C#)

以下のC#コードは、Visitorパターンの基本的な実装例を示しています。

using System;
using System.Collections.Generic;

// Element interface
public interface IElement {
    void Accept(IVisitor visitor);
}

// Concrete Element
public class ConcreteElementA : IElement {
    public void Accept(IVisitor visitor) {
        visitor.VisitConcreteElementA(this);
    }

    public string ExclusiveMethodOfConcreteElementA() {
        return "A";
    }
}

// Another Concrete Element
public class ConcreteElementB : IElement {
    public void Accept(IVisitor visitor) {
        visitor.VisitConcreteElementB(this);
    }

    public string ExclusiveMethodOfConcreteElementB() {
        return "B";
    }
}

// Visitor interface
public interface IVisitor {
    void VisitConcreteElementA(ConcreteElementA element);
    void VisitConcreteElementB(ConcreteElementB element);
}

// Concrete Visitor
public class ConcreteVisitor1 : IVisitor {
    public void VisitConcreteElementA(ConcreteElementA element) {
        Console.WriteLine($"{element.ExclusiveMethodOfConcreteElementA()} visited by ConcreteVisitor1");
    }

    public void VisitConcreteElementB(ConcreteElementB element) {
        Console.WriteLine($"{element.ExclusiveMethodOfConcreteElementB()} visited by ConcreteVisitor1");
    }
}

// Client class
public class Client {
    public static void Main() {
        var elements = new List {
            new ConcreteElementA(),
            new ConcreteElementB()
        };

        var visitor1 = new ConcreteVisitor1();

        foreach (var element in elements) {
            element.Accept(visitor1);
        }
    }
}

このコードでは、各Element(ConcreteElementAとConcreteElementB)がVisitor(ここではConcreteVisitor1)を受け入れ、VisitorがElementに対して操作を行うことができるようになっています。このようにして、Elementのクラスを変更することなく、新たなVisitorを追加することで異なる操作を容易に実装することができます。

Visitorパターンによる問題解決

教授:「今日は、Visitorパターンの魅力と、それを適用することで何が解決するのかを見ていこう。」

生徒:「はい、よろしくお願いします。Visitorパターンって具体的にどんな問題を解決してくれるんですか?」

Visitorパターンの基本

教授:「Visitorパターンは、オブジェクト構造内の要素に対して、外部から操作を加えるためのデザインパターンだよ。このパターンを使うことで、要素クラスを変更することなく、新しい操作を簡単に追加できるようになるんだ。」

問題解決の具体例

生徒:「オブジェクトの構造を変えずに新しい操作を追加できるのは便利ですね。でも、実際にどんな問題が解決するんですか?」

教授:「たとえば、異なる種類のオブジェクト集合に対して、様々な操作(例えば、表示、エクスポートなど)を行いたい場合がある。各オブジェクトに個別にメソッドを実装すると、新しい操作を追加するたびに全てのオブジェクトクラスを更新する必要がある。これは、メンテナンスが大変になる原因の一つだよ。」

生徒:「なるほど、それをVisitorパターンを使うことで、新しい操作を簡単に追加できるようになるんですね。」

教授:「正解!さらに、Visitorパターンを利用することで、オブジェクト構造から処理の詳細を分離できる。これにより、オブジェクト構造のクラスを変更することなく、新しい処理を柔軟に追加できるんだ。」

生徒:「それは、大規模なプロジェクトにおいて、特に重要なメリットですね。」

教授:「その通り。Visitorパターンは、特にシステムが大きく成長する可能性がある場合に、非常に役立つデザインパターンなんだ。」