🦔

★ Java | ドメイン駆動設計とインターフェースの多重継承の活用

2025/03/13に公開

Java

ドメイン駆動設計とインターフェースの多重継承の活用

ドメイン駆動設計(DDD)において、インターフェースの多重継承を活用した具体例。
この例では、エンティティ、リポジトリ、サービスの役割を持つインターフェースを定義し、それを実装するクラスを作成している。

  • DDDの構成要素
構成要素 内容
エンティティ ユーザーや商品などの識別可能なオブジェクト。
リポジトリ エンティティの永続化を管理するオブジェクト。
サービス ビジネスロジックを実装するオブジェクト。
  • インターフェースの定義
    エンティティ、リポジトリ、サービスのインターフェースを定義する。
// エンティティインターフェース
interface UserEntity {
    String getId();
    String getName();
}

// リポジトリインターフェース
interface UserRepository {
    void save(UserEntity user);
    UserEntity findById(String id);
}

// サービスインターフェース
interface UserService {
    void registerUser(String name);
    UserEntity getUser(String id);
}
  • インターフェースの実装
    これらのインターフェースを実装するクラスを作成する。
// ユーザーエンティティの実装
class User implements UserEntity {
    private String id;
    private String name;

    public User(String id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public String getName() {
        return name;
    }
}

// ユーザーリポジトリの実装
class InMemoryUserRepository implements UserRepository {
    private Map<String, UserEntity> users = new HashMap<>();

    @Override
    public void save(UserEntity user) {
        users.put(user.getId(), user);
    }

    @Override
    public UserEntity findById(String id) {
        return users.get(id);
    }
}

// ユーザーサービスの実装
class UserServiceImpl implements UserService {
    private UserRepository userRepository;

    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public void registerUser(String name) {
        String id = UUID.randomUUID().toString();
        UserEntity user = new User(id, name);
        userRepository.save(user);
    }

    @Override
    public UserEntity getUser(String id) {
        return userRepository.findById(id);
    }
}
  • 使用例
    これらのクラスを使用してユーザーを登録し、取得する例を示す。
public class Main {
    public static void main(String[] args) {
        UserRepository userRepository = new InMemoryUserRepository();
        UserService userService = new UserServiceImpl(userRepository);

        // ユーザーを登録
        userService.registerUser("山田太郎");

        // ユーザーを取得
        UserEntity user = userService.getUser("1"); // IDは適切に設定する必要がある。
        System.out.println("ユーザー名: " + user.getName());
    }
}


例2: ユーザー管理システム

インターフェースの定義

構成要素 内容
UserEntity ユーザーの基本情報を提供するインターフェース。
UserRepository ユーザーの永続化に関するメソッドを定義するインターフェース。
UserService ユーザーに関するビジネスロジックを提供するインターフェース。
Auditable 監査情報を提供するインターフェース。
// ユーザーエンティティのインターフェース
interface UserEntity {
    String getId();
    String getName();
}

// ユーザーリポジトリのインターフェース
interface UserRepository {
    void save(UserEntity user);
    UserEntity findById(String id);
}

// ユーザーサービスのインターフェース
interface UserService {
    void registerUser(String name);
    UserEntity getUser(String id);
}

// 監査情報を提供するインターフェース
interface Auditable {
    String getCreatedAt();
    String getUpdatedAt();
}
  • ユーザーエンティティの実装
// ユーザーエンティティの実装
class User implements UserEntity, Auditable {
    private String id;
    private String name;
    private String createdAt;
    private String updatedAt;

    public User(String id, String name) {
        this.id = id;
        this.name = name;
        this.createdAt = LocalDateTime.now().toString();
        this.updatedAt = LocalDateTime.now().toString();
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getCreatedAt() {
        return createdAt;
    }

    @Override
    public String getUpdatedAt() {
        return updatedAt;
    }
}
  • ユーザーリポジトリの実装
// ユーザーリポジトリの実装
class InMemoryUserRepository implements UserRepository {
    private Map<String, UserEntity> users = new HashMap<>();

    @Override
    public void save(UserEntity user) {
        users.put(user.getId(), user);
    }

    @Override
    public UserEntity findById(String id) {
        return users.get(id);
    }
}
  • ユーザーサービスの実装
// ユーザーサービスの実装
class UserServiceImpl implements UserService {
    private UserRepository userRepository;

    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public void registerUser(String name) {
        String id = UUID.randomUUID().toString();
        UserEntity user = new User(id, name);
        userRepository.save(user);
    }

    @Override
    public UserEntity getUser(String id) {
        return userRepository.findById(id);
    }
}
  • メインクラス
public class Main {
    public static void main(String[] args) {
        UserRepository userRepository = new InMemoryUserRepository();
        UserService userService = new UserServiceImpl(userRepository);

        // ユーザーを登録
        userService.registerUser("山田太郎");

        // ユーザーを取得
        UserEntity user = userService.getUser("1"); // IDは適切に設定する必要がある。
        System.out.println("ユーザー名: " + user.getName());
        System.out.println("作成日時: " + ((Auditable) user).getCreatedAt());
    }
}


例3: チェーン店の各店舗の売り上げ、進捗、地域別メニュー、全国メニューを管理するための具体例

クラス 内容
SalesManagement 売上を記録し、合計売上を取得するためのメソッドを定義。
ProgressTracking 進捗を更新し、現在の進捗を取得するためのメソッドを定義。
RegionalMenu 地域別メニューを管理するためのメソッドを定義。
NationalMenu 全国メニューを管理するためのメソッドを定義。
Store これらのインターフェースを実装し、店舗の売上、進捗、地域別メニュー、全国メニューを管理。

このように、インターフェースの多重継承を活用することで、異なるドメインの振る舞いを持つクラスを作成し、チェーン店の店舗の機能を効果的に管理することができる。

import java.util.ArrayList;
import java.util.List;

// 売上を管理するインターフェース
interface SalesManagement {
    void recordSale(double amount);
    double getTotalSales();
}

// 進捗を管理するインターフェース
interface ProgressTracking {
    void updateProgress(String status);
    String getProgress();
}

// 地域別メニューを管理するインターフェース
interface RegionalMenu {
    void addRegionalMenuItem(String item);
    List<String> getRegionalMenuItems();
}

// 全国メニューを管理するインターフェース
interface NationalMenu {
    void addNationalMenuItem(String item);
    List<String> getNationalMenuItems();
}

// チェーン店の店舗クラス
class Store implements SalesManagement, ProgressTracking, RegionalMenu, NationalMenu {
    private double totalSales;
    private String progress;
    private List<String> regionalMenuItems;
    private List<String> nationalMenuItems;

    public Store() {
        this.totalSales = 0.0;
        this.progress = "初期状態";
        this.regionalMenuItems = new ArrayList<>();
        this.nationalMenuItems = new ArrayList<>();
    }

    @Override
    public void recordSale(double amount) {
        totalSales += amount;
    }

    @Override
    public double getTotalSales() {
        return totalSales;
    }

    @Override
    public void updateProgress(String status) {
        this.progress = status;
    }

    @Override
    public String getProgress() {
        return progress;
    }

    @Override
    public void addRegionalMenuItem(String item) {
        regionalMenuItems.add(item);
    }

    @Override
    public List<String> getRegionalMenuItems() {
        return regionalMenuItems;
    }

    @Override
    public void addNationalMenuItem(String item) {
        nationalMenuItems.add(item);
    }

    @Override
    public List<String> getNationalMenuItems() {
        return nationalMenuItems;
    }
}


Discussion