행위 기반 설계: 전략과 어댑터 패턴의 활용

전략 패턴은 동일한 작업 흐름 내에서 다양한 알고리즘을 교체 가능하게 만드는 디자인 접근법이다. 다음 예제는 문자열 처리 과정에서 각기 다른 전략을 적용하는 방식을 보여준다.

public abstract class TextProcessor {
    public String identifier() {
        return getClass().getSimpleName();
    }

    public abstract String transform(String input);
}

class ToUpperCase extends TextProcessor {
    @Override
    public String transform(String input) {
        return input.toUpperCase();
    }
}

class ToLowerCase extends TextProcessor {
    @Override
    public String transform(String input) {
        return input.toLowerCase();
    }
}

class WordTokenizer extends TextProcessor {
    @Override
    public String transform(String input) {
        return Arrays.toString(input.split("\\s+"));
    }
}

public class TextProcessingEngine {
    public static void execute(TextProcessor processor, String data) {
        System.out.println("Applying: " + processor.identifier());
        System.out.println(processor.transform(data));
    }

    public static void main(String[] args) {
        String text = "Design patterns enable flexible code structures";

        execute(new ToUpperCase(), text);
        execute(new ToLowerCase(), text);
        execute(new WordTokenizer(), text);
    }
}

실행 결과:

Applying: ToUpperCase  
DESIGN PATTERNS ENABLE FLEXIBLE CODE STRUCTURES  
Applying: ToLowerCase  
design patterns enable flexible code structures  
Applying: WordTokenizer  
[Design, patterns, enable, flexible, code, structures]

각 전략 클래스는 동일한 인터페이스를 따르며, 실행 시점에 원하는 변환 로직을 선택할 수 있다.

어댑터 패턴은 호환되지 않는 인터페이스를 가진 클래스들을 함께 작동하게 만든다. 기존 컴포넌트를 새로운 시스템에 통합할 때 유용하다. 아래 예제는 외부 라이브러리처럼 간주할 수 있는 LegacyTransformer를 기존 처리 프레임워크에 맞추기 위해 어댑터를 사용한다.

interface TextProcessor {
    String identifier();
    String transform(String input);
}

class LegacyTransformer {
    public String modifyText(String content) {
        if (content == null || content.isEmpty()) return content;
        char[] chars = content.toCharArray();
        for (int i = 0; i < chars.length - 1; i += 2) {
            char temp = chars[i];
            chars[i] = chars[i + 1];
            chars[i + 1] = temp;
        }
        return new String(chars);
    }
}

class LegacyAdapter implements TextProcessor {
    private LegacyTransformer legacy;

    public LegacyAdapter(LegacyTransformer legacy) {
        this.legacy = legacy;
    }

    @Override
    public String identifier() {
        return legacy.getClass().getSimpleName();
    }

    @Override
    public String transform(String input) {
        return legacy.modifyText(input);
    }
}

public class AdapterDemo {
    public static void main(String[] args) {
        String sample = "hello";
        LegacyAdapter adapter = new LegacyAdapter(new LegacyTransformer());
        System.out.println("Adapting with: " + adapter.identifier());
        System.out.println(adapter.transform(sample));
    }
}

출력 결과:

Adapting with: LegacyTransformer  
ehllo

어댑터는 LegacyTransformermodifyText 메서드를 TextProcessor 인터페이스의 transform으로 래핑하여 기존 코드와 새로운 요구 사항 사이의 연결고리를 제공한다.

태그: 디자인패턴 전략패턴 어댑터패턴 자바 객체지향프로그래밍

6월 30일 02:28에 게시됨