동작 파라미터화란?

60jong·2023년 6월 22일
0

Java

목록 보기
11/14
post-thumbnail

동작 파라미터화

동작 파라미터화(Behavior Parameterization)란 메서드의 동작파라미터로 받음으로써 변화에 대응하기 좋은 디자인 패턴이다.

예시로, 서비스에 User가 두 부류(Member, Designer)가 있다고 할 때, 한 서비스 객체에서 userList 중 Member만을 / Designer만을 filtering하는 메서드가 있다고 하자.

동작 파라미터화 없이

이를 구현하는 방법으로는 가장 간단하게 구현해보겠다.

public UserFilterService {
	public List<Member> filterMembers(List<User> users) {
    	return users.stream
        	 		.filter(user -> user.getRole().equals("MEMBER"))
                    .collect(Collectors.toList());
    }
    
    public List<Designer> filterDesigners(List<User> users) {
    	return users.stream
        	 		.filter(user -> user.getRole().equals("DESIGNER"))
                    .collect(Collectors.toList());
    }
}

위처럼 구현할 수 있을 것이다. 그런데 이 구현에는 두 가지 문제점을 제기할 수 있다.

  • 두 메서드는 "MEMBER" / "DESIGNER" 말고 다른 부분이 없다. (중복의 문제)
  • 추가적인 요구사항이 있을 경우에는, 그에 따라 계속 메서드를 추가해야한다. (feat 중복)

그렇다면 동작 파라미터화를 적용해보자.

동작 파라미터화의 적용

public CustomUserService {
	public List<Member> filter(List<User> users, UserPredicate userPredicate) {
    	return users.stream
        	 		.filter(userPredicate::test)
                    .collect(Collectors.toList());
    }
}

결과부터 보자면 하나의 메서드로 구현이 끝났다. 달라진 점은 UserPredicate객체를 파라미터로 받아서 stream의 filter에서 userPredicatetest메서드 참조를 통해 구현했다.
(UserPredicate는 인터페이스로서, 전략패턴을 적용)

UserPredicate 전략 구현

public MemberPredicate implements UserPredicate {
	@Override
    public boolean test(CustomUser user) {
        return user.getRole().equals("MEMBER");
    }
}

public class DesignerPredicate implements CustomUserPredicate {
    @Override
    public boolean test(CustomUser user) {
        return user.getRole().equals("DESIGNER");
    }
}

이렇게 메서드의 동작(Member/Designer filter)을 파라미터를 통해 전달함으로써 추가적인 요구사항에 대응하기 쉬워진다. (추가적인 전략 추가는 필요)

함수형 프로그래밍 적용

여기서 더 나아갈 수 있는 방법이 있다. Java 8 이후의 함수형 프로그래밍을 적용하는 것이다.

public class Main {
	public static void main(String[] args) {
        List<CustomUser> customUsers = new ArrayList<>(List.of(
                new Member("memberA"),
                new Member("memberB"),
                new Designer("designerA"),
                new Designer("designerB")
            )
        );
        
        CustomUserService customUserService = new CustomUserService();
    	
        // 전략패턴 사용
        customUserService.filter(userList, new MemberPredicate())
    	// 람다식을 통해 전략 구현
        customUserService.filter(userList, customUser -> customUser.getRole().equals("MEMBER"));
    }
}

결론

동작 파라미터화는 여러 전략이 필요한 경우 + 반복되는 코드가 예상될 때 사용하면 좋을 것 같다.

profile
울릉도에 별장 짓고 싶다

0개의 댓글