디자인 패턴은 유용하다.
람다 표현식을 디자인 패턴에 적용한다면 더 간결하게 구현할 수 있다.
의무 체인 패턴
한 객체가 어떤 작업을 처리하고 다른 객체로 결과를 전달하여 또 다른 작업을 처리할 때 사용된다.
자동차 객체가 있다고 가정하자. 자동차 객체는 연비와, 속도, 사이즈의 필드변수를 가지고 있다.
코드로 살펴보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public class Car {
private int fuelEfficiency;
private int speed;
private int size;
public Car(final int fuelEfficiency, final int speed, final int size) {
this.fuelEfficiency = fuelEfficiency;
this.speed = speed;
this.size = size;
}
public int getSize() {
return size;
}
public int getFuelEfficiency() {
return fuelEfficiency;
}
public int getSpeed() {
return speed;
}
}
|
자동차객체를 튜닝하는 과정을 의무체인으로 구현해보려고 한다.
연비를 높여주는 객체, 속도를 올려주는 객체, 사이즈를 키우는 객체가 있다.
그리고 이 3개의 객체는 Tuner 라는 추상클래스로 묶여있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public abstract class Tuner {
protected Tuner tuner;
public void setTuner(Tuner tuner) {
this.tuner = tuner;
}
public Car tuning(Car car) {
Car newCar = upgrade(car);
if (tuner != null) {
return tuner.tuning(newCar);
}
return newCar;
}
abstract protected Car upgrade(Car car);
}
|
1
2
3
4
5
6
7
8
9
10
|
public class FuelEfficiencyUpgrader extends Tuner {
@Override
protected Car upgrade(Car car) {
int efficiency = car.getFuelEfficiency();
int speed = car.getSpeed();
int size = car.getSize();
return new Car(efficiency + 2, speed, size);
}
}
|
1
2
3
4
5
6
7
8
9
10
|
public class SpeedUpgrader extends Tuner {
@Override
protected Car upgrade(Car car) {
int efficiency = car.getFuelEfficiency();
int speed = car.getSpeed();
int size = car.getSize();
return new Car(efficiency, speed + 10, size);
}
}
|
1
2
3
4
5
6
7
8
9
10
|
public class SizeUpgrader extends Tuner {
@Override
protected Car upgrade(Car car) {
int efficiency = car.getFuelEfficiency();
int speed = car.getSpeed();
int size = car.getSize();
return new Car(efficiency, speed, size + 1);
}
}
|
위의 코드를 실행하는 Main 클래스는 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public class Main {
public static void main(String[] args) {
Car car = new Car(10, 90, 1);
System.out.println("연비 : " + car.getFuelEfficiency());
System.out.println("속도 : " + car.getSpeed());
System.out.println("크기 : " + car.getSize());
Tuner fuelEfficiencyTuner = new FuelEfficiencyUpgrader();
Tuner speedTuner = new SpeedUpgrader();
Tuner sizeTuner = new SizeUpgrader();
fuelEfficiencyTuner.setTuner(speedTuner);
speedTuner.setTuner(sizeTuner);
Car newCar = fuelEfficiencyTuner.tuning(car);
System.out.println("업그레이드된 차의 연비 : " + newCar.getFuelEfficiency());
System.out.println("업그레이드된 차의 속도 : " + newCar.getSpeed());
System.out.println("업그레이드된 차의 크기 : " + newCar.getSize());
//출력 결과
// 연비 : 10
// 속도 : 90
// 크기 : 1
// 업그레이드된 차의 연비 : 12
// 업그레이드된 차의 속도 : 100
// 업그레이드된 차의 크기 : 2
}
}
|
람다 표현식 사용
람다 표현식을 사용한다면 Tuner 와 Tuner 를 상속받는 클래스들 없이 Car 객체를 튜닝할 수 있다.
우리에게 필요한 건 단지 Car 객체와 람다 표현식을 사용한 Main 클래스 뿐이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public class Car {
private int fuelEfficiency;
private int speed;
private int size;
public Car(final int fuelEfficiency, final int speed, final int size) {
this.fuelEfficiency = fuelEfficiency;
this.speed = speed;
this.size = size;
}
public int getSize() {
return size;
}
public int getFuelEfficiency() {
return fuelEfficiency;
}
public int getSpeed() {
return speed;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
import java.util.function.Function;
import java.util.function.UnaryOperator;
public class Main {
public static void main(String[] args) {
Car oldCar = new Car(10, 90, 1);
System.out.println("연비 : " + oldCar.getFuelEfficiency());
System.out.println("속도 : " + oldCar.getSpeed());
System.out.println("크기 : " + oldCar.getSize());
UnaryOperator<Car> fuelEfficiencyTuner =
car -> new Car(car.getFuelEfficiency() + 2, car.getSpeed(), car.getSize());
UnaryOperator<Car> speedTuner =
car -> new Car(car.getFuelEfficiency(), car.getSpeed() + 10, car.getSize());
UnaryOperator<Car> sizeTuner =
car -> new Car(car.getFuelEfficiency(), car.getSpeed(), car.getSize() + 1);
Function<Car, Car> pipeLine =
fuelEfficiencyTuner.andThen(speedTuner).andThen(sizeTuner);
Car newCar = pipeLine.apply(oldCar);
System.out.println("업그레이드된 차의 연비 : " + newCar.getFuelEfficiency());
System.out.println("업그레이드된 차의 속도 : " + newCar.getSpeed());
System.out.println("업그레이드된 차의 크기 : " + newCar.getSize());
//출력 결과
// 연비 : 10
// 속도 : 90
// 크기 : 1
// 업그레이드된 차의 연비 : 12
// 업그레이드된 차의 속도 : 100
// 업그레이드된 차의 크기 : 2
}
}
|
※ 람다 표현식을 사용하는 것이 항상 좋은 것은 아니다.
불필요한 코드를 제거할 수 있어서 람다 표현식이 유용할 수 있고, 경우에 따라 기존의 방식을 고수하는 것이 더 좋을 수 있다.
반응형
'Java' 카테고리의 다른 글
Optional 정리 (0) | 2020.04.18 |
---|---|
람다 표현식을 활용한 디자인패턴 - 팩토리 패턴 (0) | 2020.04.14 |
람다 표현식을 활용한 디자인패턴 - 옵저버 패턴 (0) | 2020.04.08 |
람다 표현식을 활용한 디자인패턴 - 템플릿 메서드 (0) | 2020.04.08 |
람다 표현식을 활용한 디자인패턴 - 전략 패턴 (0) | 2020.04.08 |