主要な5つのデザインパターン:構造と実装方法の解説

1. Singleton(シングルトン)パターン

Singletonパターンは、あるクラスのインスタンスがシステム全体で唯一であることを保証し、そのインスタンスへのグローバルなアクセスポイントを提供します。リソース管理やログ出力、設定情報の保持などに利用されます。

スレッドセーフなダブルチェックロッキング (Double-Checked Locking)

遅延初期化を行いながら、マルチスレッド環境でのパフォーマンスを維持する実装です。

public class DatabaseConnection {
    private static volatile DatabaseConnection connectionInstance;

    private DatabaseConnection() {}

    public static DatabaseConnection getInstance() {
        if (connectionInstance == null) {
            synchronized (DatabaseConnection.class) {
                if (connectionInstance == null) {
                    connectionInstance = new DatabaseConnection();
                }
            }
        }
        return connectionInstance;
    }
}

静的内部クラスによる実装 (Initialization-on-demand holder idiom)

Javaのクラスロードの仕組みを利用した、非常に効率的で推奨される手法です。

public class GlobalSettings {
    private GlobalSettings() {}

    private static class SettingsHolder {
        private static final GlobalSettings INSTANCE = new GlobalSettings();
    }

    public static GlobalSettings getInstance() {
        return SettingsHolder.INSTANCE;
    }
}

2. Factory(工場)パターン

Factoryパターンは、オブジェクトの生成ロジックをカプセル化し、クライアント側が具体的なクラスを知らなくてもインスタンスを取得できるようにします。

Simple Factory (簡易工場)

静的メソッドを使用して、引数に基づいて異なるインスタンスを返します。

public class StorageFactory {
    public static CloudStorage getStorage(String type) {
        if ("AWS".equalsIgnoreCase(type)) {
            return new S3Storage();
        } else if ("Azure".equalsIgnoreCase(type)) {
            return new BlobStorage();
        }
        throw new IllegalArgumentException("Unknown storage type");
    }
}

Factory Method (工場メソッド)

生成のためのインターフェースを定義し、どのクラスをインスタンス化するかはサブクラスに決定させます。

public abstract class DocumentCreator {
    public abstract Document createDocument();
}

public class PdfCreator extends DocumentCreator {
    @Override
    public Document createDocument() {
        return new PdfDocument();
    }
}

Abstract Factory (抽象工場)

互いに関連する製品群を、具体的なクラスを指定せずに生成するためのインターフェースを提供します。

public interface UIComponentFactory {
    Button createButton();
    Checkbox createCheckbox();
}

public class DarkModeFactory implements UIComponentFactory {
    public Button createButton() { return new DarkButton(); }
    public Checkbox createCheckbox() { return new DarkCheckbox(); }
}

3. Proxy(プロキシ)パターン

あるオブジェクトへのアクセスを制御するために、その代理(プロキシ)となるオブジェクトを提供します。遅延初期化、アクセス権限のチェック、ロギングなどに用いられます。

public interface Resource {
    void load();
}

public class SecureResourceProxy implements Resource {
    private RealResource realResource;
    private String userRole;

    public SecureResourceProxy(String role) {
        this.userRole = role;
    }

    @Override
    public void load() {
        if ("ADMIN".equals(userRole)) {
            if (realResource == null) {
                realResource = new RealResource();
            }
            realResource.load();
        } else {
            System.out.println("Access Denied: Admin role required.");
        }
    }
}

4. Decorator(デコレータ)パターン

既存のオブジェクトに、継承を使わずに動的に新しい機能や振る舞いを追加します。「ラッパー」とも呼ばれます。

public interface Message {
    String getContent();
}

public class BasicMessage implements Message {
    public String getContent() { return "Hello"; }
}

public abstract class MessageDecorator implements Message {
    protected Message decoratedMessage;
    public MessageDecorator(Message m) { this.decoratedMessage = m; }
}

public class EncryptionDecorator extends MessageDecorator {
    public EncryptionDecorator(Message m) { super(m); }

    @Override
    public String getContent() {
        return Base64.getEncoder().encodeToString(decoratedMessage.getContent().getBytes());
    }
}

5. Builder(ビルダー)パターン

複雑なオブジェクトの構築過程をその表現から分離し、同じ構築過程で異なる表現を生成できるようにします。多くのフィールドを持つオブジェクトを生成する際に有効です。

public class ServerConfig {
    private final String host;
    private final int port;
    private final boolean useSsl;

    private ServerConfig(Builder builder) {
        this.host = builder.host;
        this.port = builder.port;
        this.useSsl = builder.useSsl;
    }

    public static class Builder {
        private String host;
        private int port = 8080;
        private boolean useSsl = false;

        public Builder setHost(String host) {
            this.host = host;
            return this;
        }

        public Builder setPort(int port) {
            this.port = port;
            return this;
        }

        public Builder enableSsl() {
            this.useSsl = true;
            return this;
        }

        public ServerConfig build() {
            return new ServerConfig(this);
        }
    }
}

// 使用例
ServerConfig config = new ServerConfig.Builder()
    .setHost("localhost")
    .setPort(443)
    .enableSsl()
    .build();

タグ: Java DesignPatterns SoftwareArchitecture ObjectOriented

11月5日 12:44 投稿