代わりによろしく！Proxyパターン！

## はじめに
こんにちは！絶賛デザインパターン学習中のGUです！今回はデザインパターンの中の一つであるProxyパターンについて学んだことをまとめていきます！

「プロキシ」という言葉をご存知でしょうか？**代理**という訳があてられています。社内でPCを使っているとき、よく耳にする(かもしれない)言葉だと思います。プロキシは、直接サイトにアクセスするのではなく、間にプロキシサーバーを介してアクセスを行う仕組みです。これにより、アクセスしてはいけないサイトへの接続を防ぐための追加の処理を埋め込むことができます。本来のサーバーではなく**代理で**プロキシサーバーを介してサイトへ接続するのです。

Proxyパターンは上でのプロキシのように何かを行うとき本来のものではなく**代理**のものに処理を行ってもらうようにするパターンです。

今回はキャッシュを用いた画像取得を行い表示するプログラムを例にします。
一回ロードしたことのある画像はもう一度ロードするのではなく代わりにキャッシュから持ってきた方がパフォーマンスはいいですよね。
普段はプロキシである、キャッシュから画像を取得するクラスが画像取得を代理で行い、それができなければ本来の画像を取得するクラスが画像取得を行うように設計します。

![2024-08-30_17h30_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629646/1aeec488-88f3-5d84-7cd3-65174ee4bfe0.png)


## 実装例

```C#:ImageLoader.cs
/// <summary>
/// 画像をロードするインターフェース
/// </summary>
public interface ImageLoader
{
    /// <summary>
    /// 画像をロードする
    /// </summary>
    /// <param name="filename">ファイル名</param>
    BitmapSource Load(string filename);
}
```

```C#:BitmapImageLoader.cs
 /// <summary>
 /// キャッシュを用いずに画像のロードを行うクラス
 /// </summary>
 class BitmapImageLoader : ImageLoader
 {
     public static BitmapImageLoader m_Instance = new BitmapImageLoader();

     public static BitmapImageLoader GetInstance()
     {
         return m_Instance;
     }

     /// <summary>
     /// BitmapImageLoaderのコンストラクタ
     /// </summary>
     private BitmapImageLoader()
     {
     }

     /// <summary>
     /// 引数のファイル名の画像をロードする
     /// </summary>
     public BitmapSource Load(string filename)
     {
         BitmapImage bitmap = new BitmapImage();
         bitmap.BeginInit();
         bitmap.UriSource = new Uri(filename);
         bitmap.EndInit();
         bitmap.Freeze();

         return bitmap;

     }
 }
 ```

 ```C#:CashImageLoader.cs
 /// <summary>
/// キャッシュを利用して画像を取得するクラス
/// </summary>
class CashImageLoader : ImageLoader
{
    private static CashImageLoader m_Instance = new CashImageLoader();

    public static CashImageLoader GetInstance()
    {
        return m_Instance;
    }

    /// <summary>
    /// ロードした画像を格納するキャッシュ
    /// </summary>
    private Dictionary<string, BitmapSource> m_Cash = new Dictionary<string, BitmapSource>();

     /// <summary>
     /// CashImageLoaderのコンストラクタ
     /// </summary>
    private CashImageLoader()
    {

    }

    /// <summary>
    /// キャッシュから画像を取得する
    /// </summary>
    public BitmapSource Load(string filename)
    {
        if (m_Cash.ContainsKey(filename))
        {
            return m_Cash[filename];
        }
        BitmapSource bitmap = BitmapImageLoader.GetInstance().Load(filename);
        m_Cash[filename] = bitmap;
        return bitmap;
    }
}
 ```

 ```C#:MainWindow.xaml.cs

/// <summary>
/// MainWindow.xamlの相互ロジック
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }


    private void m_Button_OnClick(object sender, RoutedEventArgs e)
    {
        var od = new OpenFileDialog();

        od.Filter = "画像ファイル|*.bmp;*.jpg;*.jpeg;*.png;*.gif";
        if (od.ShowDialog() == true)
        {
            string filename = od.FileName;
            ImageLoader loader = CashImageLoader.GetInstance();
            BitmapSource bitmap = loader.Load(filename);
            m_Image.Source = bitmap;
        }
    }
}
 ```

 上のコードでは、画像を取得する際、まずはProxy(代理)であるCashImageLoaderクラスが画像取得を行い、それができなければ本来の画像取得のためのクラスであるBitmapImageLoaderクラスが画像取得を行う実装になっています。これにより無駄な画像アクセスをしないよう制御することができます。
 
 Proxyパターンのメリットとしては上のように、直接画像を取得させないようオブジェクトへのアクセスを制限するなど、**本来の処理を用途に応じて変更した処理を代理に行ってもらうようにすることでオブジェクトを扱いやすくできること**です。

 ## おわりに

今回はProxyパターンについてまとめました。今後もデザインパターン、SOLID原則など開発に必要な知識を取得していきます。同じく勉強中の皆様がんばっていきましょー！！