👋

Javaでデリゲートメモ

2024/12/10に公開

Javaでデリゲートメモ

interfaceでデリゲート処理の例

interface MyDelegate {
    void doSomething();
}

class MyClass {
    private MyDelegate delegate;

    public void setDelegate(MyDelegate delegate) {
        this.delegate = delegate;
    }

    public void    performAction() {
        if (delegate != null) {
            delegate.doSomething(); 
        }
    }
}

class MyConcreteDelegate implements MyDelegate { 
    @Override
    public void doSomething() {
        System.out.println("具体的な処理を実行します!"); 
    }
}

public class Main { // または任意のクラス名
    public static void main(String[] args) {
        MyClass myObject = new MyClass();
        myObject.setDelegate(new MyConcreteDelegate()); 
        myObject.performAction(); // 出力: 具体的な処理を実行。
    }
}

解説

  • interface MyDelegate:これはインターフェースで、doSomething() というメソッドの型を定義しています。インターフェースは、クラスが実装すべきメソッドの仕様を定めるものです。
  • class MyClass:このクラスは、MyDelegate型の変数 delegate を持ちます。setDelegateメソッドでこのdelegateに具体的な処理を行うオブジェクトを設定します。performActionメソッドでは、設定されたdelegateが存在すれば、そのdoSomething()メソッドを呼び出します。
  • class MyConcreteDelegate implements MyDelegate:このクラスは、MyDelegateインターフェースを実装しています。つまり、MyDelegateで定義されたdoSomething()メソッドを具体的に実装しています。この例では、doSomething()メソッドが呼び出されると「具体的な処理を実行します!」とコンソールに出力します。
  • public class Main { ... }:これはメインクラスで、プログラムの実行開始点となります。
  • MyClass myObject = new MyClass();:MyClassの新しいインスタンスを作成します。
  • myObject.setDelegate(new MyConcreteDelegate());:MyConcreteDelegateの新しいインスタンスを作成し、それをmyObjectのdelegateに設定します。これにより、myObjectはperformAction()を呼び出した際に、MyConcreteDelegateのdoSomething()を実行するようになります。
  • myObject.performAction();:myObjectのperformAction()メソッドを呼び出します。これにより、delegate(ここではMyConcreteDelegateのインスタンス)のdoSomething()メソッドが実行され、「具体的な処理を実行します!」と出力されます。

ポイント

  • デリゲートパターンは、あるオブジェクトが特定の処理を別のオブジェクトに委譲するデザインパターン。

  • Javaではインターフェースを使ってデリゲートパターンを実装する。

  • この例では、MyClassはMyDelegateインターフェースを実装したオブジェクトに処理を委譲しています。

  • 実際には、「// ...」の部分に、MyClassやMyConcreteDelegateを利用する具体的なコードが書かれることになる。

  • https://github.com/DonBranson/MockitoMatcherExamples

実装例

import java.util.*;
import java.lang.*;
import java.io.*;

// Calculator インターフェースと、それを実装する SimpleCalculator, AdvancedCalculator クラス
interface Calculator {
    int add(int a, int b);
    int subtract(int a, int b);
    int multiply(int a, int b);
    int divide(int a, int b);
}

class SimpleCalculator implements Calculator {
    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public int subtract(int a, int b) {
        return a - b;
    }

    @Override
    public int multiply(int a, int b) {
        return a * b;
    }

    @Override
    public int divide(int a, int b) {
        return a / b; // 0除算のチェックは行わない
    }
}

class AdvancedCalculator implements Calculator {
    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public int subtract(int a, int b) {
        return a - b;
    }

    @Override
    public int multiply(int a, int b) {
        return a * b;
    }

    @Override
    public int divide(int a, int b) {
        if (b == 0) {
            throw new ArithmeticException("0による除算はできません");
        }
        return a / b;
    }
}

// MyDelegate インターフェース、MyClass、MyConcreteDelegate クラス
interface MyDelegate {
    void doSomething();
}

class MyClass {
    private MyDelegate delegate;
    private Calculator calculatorDelegate; // Calculator型のデリゲートを追加

    public void setDelegate(MyDelegate delegate) {
        this.delegate = delegate;
    }

    public void setCalculatorDelegate(Calculator calculatorDelegate) {
        this.calculatorDelegate = calculatorDelegate;
    }

    public void performAction() {
        if (delegate != null) {
            delegate.doSomething(); 
        }
    }

    public int performAction(int a, int b, String operation) {
        if (calculatorDelegate != null) {
            switch (operation) {
                case "add":
                    return calculatorDelegate.add(a, b);
                case "subtract":
                    return calculatorDelegate.subtract(a, b);
                case "multiply":
                    return calculatorDelegate.multiply(a, b);
                case "divide":
                    return calculatorDelegate.divide(a, b);
                default:
                    throw new IllegalArgumentException("不正な演算子: " + operation);
            }
        } else {
            throw new IllegalStateException("デリゲートが設定されていません");
        }
    }
}

class MyConcreteDelegate implements MyDelegate { 
    @Override
    public void doSomething() {
        System.out.println("具体的な処理を実行します!"); 
    }
}

// Main クラス (実行部分)
public class Main {
    public static void main(String[] args) {
        MyClass myObject = new MyClass();

        // MyConcreteDelegate をデリゲートとして設定して実行
        myObject.setDelegate(new MyConcreteDelegate()); 
        myObject.performAction(); // 出力: 具体的な処理を実行します!

        // SimpleCalculator をデリゲートとして設定して実行
        myObject.setCalculatorDelegate(new SimpleCalculator());
        System.out.println("SimpleCalculator:");
        System.out.println("5 + 3 = " + myObject.performAction(5, 3, "add")); 
        System.out.println("5 - 3 = " + myObject.performAction(5, 3, "subtract")); 
        System.out.println("5 * 3 = " + myObject.performAction(5, 3, "multiply")); 
        System.out.println("5 / 3 = " + myObject.performAction(5, 3, "divide")); 

        // AdvancedCalculator をデリゲートとして設定して実行
        myObject.setCalculatorDelegate(new AdvancedCalculator());
        System.out.println("\nAdvancedCalculator:");
        System.out.println("5 + 3 = " + myObject.performAction(5, 3, "add")); 
        System.out.println("5 - 3 = " + myObject.performAction(5, 3, "subtract")); 
        System.out.println("5 * 3 = " + myObject.performAction(5, 3, "multiply")); 
        try {
            System.out.println("5 / 0 = " + myObject.performAction(5, 0, "divide")); 
        } catch (ArithmeticException e) {
            System.out.println("0による除算のエラー: " + e.getMessage()); 
        }
    }
}

Discussion