1. 검색을 위한 스펙

식별자 외에 다양한 조건으로 애그리거트를 찾으려면 어떻게 해야 할까?

⇒ specification(스펙) 사용!

public interface Specifation<T>{
	public boolean isSatisfiedBy(T agg);
}

→ agg(애그리거트 객체)가 조건을 충족하는지 boolean값을 리턴한다.

public class OrdereSpec implements Specification<Order> {
	private String ordererId;
	public OrdererSpec(String ordererId) {
		this.ordererId = ordererId; //비교 대상
	}
	//Order 애그리거트 객체가 특정 고객의 주문인지 확인하는 스펙 구현
	public boolean isSatisfiedBy(Order agg) {
		return agg.getOrdererId().getMemberId().getId().equals(ordererId);
	}
}
public class MemoryOrderRepository implements OrderRepository {
	public List<Order> findAll(**Specification spec**) {
		List<Order> allOrders = findAll();
		return allOrders.stream().filter(order -> **spec.isSatisfiedBy(order)**).collect(toList());
	}
}
Specification<Order> ordererSpec = new OrdererSpec("madvirus"); //특정 스펙 생성
List<Order> orders = orderRepository.findAll(ordererSpec); //리포지터리에 전달

스펙 조합

public class AndSpec<T> implements Specification<T> {
	private List<Specification<T>> specs;
	
	public AndSpecification(Specification<T> ... specs) {
		this.specs = Arrays.asList(specs);
	}

	public boolean isSatisfiedBy(T agg) {
		for (Specification<T> spec : specs){
			if (!spec.isSatisfiedBy(agg)) return false;
		}
		return true;
	}
}
Specification<Order> ordererSpec = new OrdererSpec("madvirus");
Specification<Order> orderDateSpec = new OrderDataSpec(fromDate,toDate);

AndSpec<T> spec = new AndSpec(ordererSpec,orderDateSpec); //여러 스펙 전달
List<Order> orders = orderRepository.findAll(spec); //and스펙을 리포지토리에 전달

2. JPA를 위한 스펙 구현