a) 다음은 명령형과 선언형 작성방식의 차이를 보여준다.
imperative style
public static int between(int l, int r, int x) {
return Math.min(Max.max(l, x), r);
}작성하는 순간 바로 연산을 처리하여 값을 얻게된다
int y = Math.between(5, 9, 13);
declarative style
class Between implements Number {
private final Number num;
Between(Number l, Number r, Number x) {
num = new Min(new Max(l, x), r);
}@Override
public int intValue() {
return num.intValue();
}
}중간값을 구한다라는 선언을 하였다.
아직 CPU에게 연산을 수행하라 명령하지 않았다.
intValue() 가 정말 필요한 시점에 호출하여 사용할 수 있다.Number y = new Between(5, 9, 13);
b) 만약 중간값을 구하는 방식을 변경하고 싶다면?
class Between implements Number {
private final Number num;
Between(Number l, Number r, Number x) {
this(new Min(new Max(l, x), r));
}Between(Number num) {
this.num = num;
}
}declarative - 다른 객체와 “조합” 할 수 있다(다형성)
Integer x= new Between(new IntegerWithOtherWay(5, 9, 13));
imperative - 재작성 외에 방법이 없다
int y = Math.between(5, 9, 13);
c) 가독성 & 응집력은 어떤 것이 더 좋을까?
List
evens = new ArrayList<>();
for (int num : numbers) {
if (num % 2 == 0) {
evens.add(num);
}
}
List
evens = new Filtered(...)
List
evens = new Filtered ( numbers, new Predicate () { @Override public boolean suitable(Integer number) { return number % 2 == 0; } } );
Utility(helper)
- 클래스가 아닌 static 함수의 집합체이다(객체를 생성하지 않는다)
class Math {
private Math() {}
public static int max(int a, int b) {
if (a < b) {
return b;
}
return a;
}
}
Singleton pattern
class Math {
private static Math INSTANCE = new Math();
private Math() {}
public static Math getInstance() {
return Math.INSTANCE;
}
public static void setInstance(Math other) {
INSTANCE = other;
}
public int max(int a, int b) {
if (a < b) {
return b;
}
return a;
}
}
다음은 어떤점이 다른가?
Math.max(1, 2); //Utility
Math.getInstance.max(1, 2); //Singleton둘의 차이점은 setInstance() 사용하여 캡슐화된 객체를 교체가능한 것 외에 다를 것이 없다
둘의 공통점은 global scope 로서 존재한다