Holder 패턴
FactoryMethod 패턴을 먼저 이야기 해보겠다.
FactoryMethod 패턴은 객체의 생성을 책임지는 패턴이다.
특히 상위 타입을 가지고 있는 여러 하위 객체들 중에서 외부에서 입력한 조건에 맞게 생성해 주는 역할을 한다. 그리고 생성된 객체를 전달해 줄 때는 상위 타입으로 캐스팅해서 리턴한다. 따라서 FactoryMethod 패턴을 구현한 클래스 외부에서는 객체의 구체적인 타입을 알 수 없다. 이것은 구체적인 타입에 의존하면서 발생하는 강한 결합과 코드의 중복 등 객체지향에서 지양하는 여러 문제들이 발생하지 않도록 방지해 준다.
Holder 패턴은 FactoryMethod 패턴과 유사점이 많다. 우선 객체의 생성을 담당한다. Holder 패턴을 구현한 클래스는 클래스 내부에서 각 하위 객체를 생성하여 가지고 있다. 그리고 외부에서 특정 조건에 맞는 객체를 요구할 경우 그에 해당하는 객체를 제공해준다. 이 경우에도 FactoryMethod와 마찬가지로 하위 객체의 타입을 알리지 않기 위해서 상위 타입으로 캐스팅해서 내보낸다. 기본적인 동작과 목적에 있어서 FactoryMethod 패턴과 Holder 패턴은 매우 유사하다.
다른 점이 딱 한가지 있다. FactoryMethod 패턴은 외부에서 객체를 요구하면 매번 생성해서 전달해 주는데 비해 Holder 패턴은 하위 객체 각각에 대하여 딱 한번씩만 생성한다는 점이다. 이 점이 FactoryMethod와 Holder 패턴을 구분하는 가장 큰 차이점이다.
그러면 이제 Holder 패턴을 구현해 보도록 하겠다. 우리는 이 예제에서 온도 상태를 나타내는 객체를 생성하고자 한다. 온도 상태 객체는 ITemperature라는 인터페이스 형태의 상위 타입을 가진다. 그리고 하위 객체들은 구체적으로 Hot / Normal / Cold 라는 상태를 표현하는 개체이다. Holder 객체는 외부에서 받은 온도 값이 30도 이상이면 Hot객체를, 0도 미만이면 Cold객체를, 나머지의 경우에는 Normal 객체를 외부에 제공하게 될 것이다.
우선 상위 타입을 나타내는 ITemperature 인터페이스를 정의하도록 한다.
package holderPattern;
public interface ITemperature {
public String toDbString();
public void operateThermostat(Thermostat thermostat);
}
이 ITemperature 인터페이스는 하위 객체의 구체적인 타입을 감추도록 만들어준다. 인터페이스에서 구현하고 있는 메소드들이 크게 중요하진 않지만 이해를 돕기 위해서 설명을 하자면 다음과 같다. 우선 toDbString() 메소드는 이 온도 상태 객체가 데이터베이스를 만났을 때 자신의 상태에 대한 문자열을 생성하여 제공해주는 메소드이다.
operateThermostat() 메소드는 각 온도 상태에 따라 온도조절기(Thermostat)를 동작시킨다. 상태 객체별로 다른 동작을 수행해야 하므로 온도조절기 객체를 인자로 받도록 되어 있다.
다음은 Hot/Normal/Cold를 나타내는 구체 객체를 구현한 코드이다.
package holderPattern;
public class HotTemperature implements ITemperature {
String dbString = "HOT";
@Override
public String toDbString() {
return dbString;
}
@Override
public void operateThermostat(Thermostat thermostat) {
thermostat.cooling();
}
}
package holderPattern;
public class NormalTemperature implements ITemperature {
String dbString = "NORMAL";
@Override
public String toDbString() {
return dbString;
}
@Override
public void operateThermostat(Thermostat thermostat) {
thermostat.stop();
}
}
package holderPattern;
public class ColdTemperature implements ITemperature {
String dbString = "COLD";
@Override
public String toDbString() {
return dbString;
}
@Override
public void operateThermostat(Thermostat thermostat) {
thermostat.cooling();
}
}
Hot/Normal/Cold 상태를 표현하는 3개의 클래스가 정의되었다. 셋은 모두 ITemperature 인터페이스를 구현하고 있고, 모두 각자의 상태에서 해야할 인터페이스들을 구현하였다.
Holder 패턴을 구현하는 TemperatureHolder 클래스는 아래와 같이 정의될 수 있다.
package holderPattern;
public class TemperatureHolder {
public static final ITemperature HOT = new HotTemperature();
public static final ITemperature NORMAL = new NormalTemperature();
public static final ITemperature COLD = new ColdTemperature();
public static ITemperature getTemperature(int temperature) {
if(temperature > 30) return HOT;
if(temperature >= 0) return NORMAL;
else return COLD;
}
}
우선 객체의 위쪽에 ITemperature 타입으로 Hot/Normal/Cold 총 3개의 객체를 선언하고 있음을 알 수 있다. 이 객체들은 단 한 개씩만 생성될 것이므로 static final 로 선언된다.
그리고 getTemperature() 라는 메소드가 있다. 이 메소드는 ITemperature타입을 리턴하도록 되어있고 온도 값(temperature)을 매개변수로 받도록 되어있다. Holder 객체는 외부에서 받은 온도 값이 30도 이상이면 Hot객체를, 0도 미만이면 Cold 객체를, 나머지의 경우 Normal 객체를 외부에 제공하도록 구현되어 있다.
출처:
effectiveprogramming.tistory.com/entry/Holder-%ED%8C%A8%ED%84%B4?category=660013