C#でデザインパターン「Visitorパターン」

C# コンピュータ
C#

Visitorパターンは、既存のクラスの構造を変更することなく、それらのクラスに対する新しい操作(メソッド)を外部から追加することを目的としたデザインパターンみたいです。

Wikipediaの「Visitorパターン」
Visitor パターン - Wikipedia

サンプルコード

/// <summary>
/// Visitorパターンのサンプルコード
/// </summary>
interface IVisitor
{
    // void Visit(IImage img);
    void Visit(Png img);
    void Visit(Jpeg img);
    void Visit(Grayscale img);
}
interface IImage
{
    void Accept(IVisitor visitor);
}
class Png : IImage
{
    public int Width {get;}
    public int Height {get;}
    public readonly int DEPS = 4;
    public Png(int width, int height)
    {
        Width = width;
        Height = height;
    }
    public void Accept(IVisitor visitor) => visitor.Visit(this);
}
class Jpeg : IImage
{
    public int Width {get;}
    public int Height {get;}
    public readonly int DEPS = 3;
    public Jpeg(int width, int height)
    {
        Width = width;
        Height = height;
    }
    public void Accept(IVisitor visitor) => visitor.Visit(this);
}
class Grayscale : IImage
{
    public int Width {get;}
    public int Height {get;}
    public readonly int DEPS = 1;
    public Grayscale(int width, int height)
    {
        Width = width;
        Height = height;
    }
    public void Accept(IVisitor visitor) => visitor.Visit(this);
}
class PixcelCountVisitor : IVisitor
{
    /*
    public void Visit(IImage img)
    {
        int result = 0;

        switch (img)
        {
            case Png png:
                result = png.Width * png.Height * png.DEPS;
                break;
            case Jpeg jpg:
                result = jpg.Width * jpg.Height * jpg.DEPS;
                break;
            case Grayscale gray:
                result = gray.Width * gray.Height * gray.DEPS;
                break;
            default:
                throw new NotSupportedException ($"未対応{img.GetType().Name}");
        }

        Console.WriteLine($"Picel:{result}");
    }
    */
    public void Visit(Png png)
    {
        int result = png.Width * png.Height * png.DEPS;
        Console.WriteLine($"Png Picel:{result}");
    }

    public void Visit(Jpeg jpg)
    {
        int result = jpg.Width * jpg.Height * jpg.DEPS;
        Console.WriteLine($"Jpeg Picel:{result}");
    }

    public void Visit(Grayscale gray)
    {
        int result = gray.Width * gray.Height * gray.DEPS;
        Console.WriteLine($"Grayscale Picel:{result}");
    }}

public class Program
{
    static public void Main()
    {
        IImage png = new Png(256, 128);
        IImage jpg = new Jpeg(256, 128);
        IImage gray = new Grayscale(256, 128);

        List<IImage> images = [png, jpg, gray];

        PixcelCountVisitor pixcelCountVisitor = new();

        foreach(IImage img in images)
        {
            img.Accept(pixcelCountVisitor);
        }
    }    
}

Visitorはオーバーロードで実装するのが一般的なようですが、個人的な好みはジェネリックを使って一つのメッソド処理する方法で、コメントアウトしたコードを残しています。

コメント