변경에 유리한 코드 작성


 

 

SportsCar car = new SportsCar();

예를 들어 위 코드를 아래 코드와 같이 변경하려면 타입인 SportsCar 부분과 new 연산자 뒤의 SportsCar() 부분두 군데를 모두 변경해주어야 한다는 것을 알 수 있다.

 

Truck car = new Truck();

 

아래 코드와 같이 다형성을 이용한다면 getCar() 메서드 내 인스턴스 생성에 대한 부분만 변경해주면 될 것이다. 따라서 이를 사용하는 사용자 코드에서는 수정할 필요가 없기 때문에 변경에 유리하다.

 

Car car = getCar();

static Car getCar() {
    return new SportsCar();
}

 

다음으로는 Map과 외부 파일을 이용하는 방식이다. config.txt를 통해 =를 구분자로 하여 Key와 Value에 대한 값을 Map 형태로 Properties에 저장한다. 이 방식은 외부 파일만 수정하면 되기 때문에 프로그램 변경할 필요가 없다는 장점을 가진다.

 

Car car = getCar();

static Car getCar() throws Exception {
    // config.txt를 읽어서 Properties에 저장
    Properties p = new Properties();
    p.load(new FileReader("config.txt"));
    
    // 클래스 객체를 얻어서
    Class clazz = Class.forName(p.getProperty("car"));
    return (Car)clazz.newInstance(); // 객체 생성 후 반환
}

 

 

 

객체 컨테이너(ApplicationContext) 만들기


AppContext  ac = new AppContext();
Car car = (Car)ac.getBean("car");
Engine engine = (Engine) ac.getBean("engine");
class AppContext {
    Map map;

    AppContext() {
        map = new HashMap();
        map.put("car", new SportsCar());
        map.put("engine", new Engine());
    }

    Object getBean(String id) { return map.get(id); }
}

 

객체 컨테이너 즉 객체 저장소를 만들고, 저장소에 Map형태(Key, Value)로 Key에 id 값과, Value에 인스턴스 주소 값을 담는다. 다음 getBean()을 통해 id(Key) 값으로 참조변수에 해당 인스턴스 주소를 담는 방식이다. 이때 getBean()은 Object 타입을 반환하기 때문에 형변환이 필요하다는 것에 주의한다.

 

AppContext() 메서드 내 하드코딩 된 부분을 바로 위에서 Map과 외부 파일을 이용하는 방식으로 바꿔주어 변경에 유리하도록 해준다.

 

class AppContext {
    Map map;

    AppContext() {

        Properties p = new Properties();
        p.load(new FileReader("config.txt"));
        map = new HashMap(p);

        for(Object key : map.keySet()) {

            Class clazz = Class.forName((String)map.get(key));
            map.put(key, clazz.newInstance());
        }
    }
}

 

 

xml 파일에 클래스 정보 설정 후 이를 읽어서 Map 형태로 객체가 만들어지고 getBean()으로 이를 사용한다.

 

getBean()은 같은 객체를 반환하는데, 그 이유는 싱글톤이기 때문이다. 때로는 매번 다른 객체를 생성하여 사용해야 하는 경우도 있는데, 이때 xml 파일의 <bean id> 내 scope를 prototype으로 지정해주면 된다.

 

setter를 직접 호출하는 대신 이 xml 파일을 통해 <property> 태그로 처리 가능하다. 기본 타입은 value, 참조 변수는 ref, 배열은 <array value-type>를 통해 값을 지정해준다. <property> 태그는 setter를 직접 호출하지 않고 사용하지 않는 방식이지만, setter를 이용한다는 것에 주의한다. setter가 아닌 생성자로 초기화 할 경우에는 <constructor-arg> 태그를 사용한다(기본 생성자도 잊지말것).

 

+ Recent posts