2013년 12월 17일 화요일
static 영역에서 싱글턴 구현 (inner class)
public class Stage{
private Stage(){}
private static class StageSingletonHolder{
static Stage instance = new Stage();
}
private static Stage getInstance(){
return StageSingletonHolder.instance;
}
}
2013년 12월 16일 월요일
전도의 유혹
2013년 12월 15일 일요일
위임과 리디렉션
디자인 스페이스라는 EDP 개념에서 메서드 호출 의존성 이론중 위임과 리디렉션의 그래프예요.
x는 메서드를 나타내고, y는 오브젝트를 나타냅니다.
유사도는 값이 클수록 비슷해지고, 값이 작을수록 달라지죠.
이래뵈도 졸트상을 수상한 그래프예요
그래프를 보시면 알겠지만, 위임은 오브젝트 유사도와 메서드 유사도의 값이 공통적으로 낮고
리디렉션은 오브젝트 유사도는 낮지만 메서드 유사도는 높은 것을 알 수 있어요.
지금부터 그래프를 토대로 해설 들어갑니당 ~
위임은 소프트웨어 설계 분야에서 다양하게 쓰이는 광범위한 뜻의 단어입니다.
여기에서 위임을 정확하게 정의하자면, 메서드 호출이 일어나는 두 객체와 두 메서드가 서로 다름을 의미합니다.
[위임 예시]
class VicePresidentOfSales
{
public :
void increaseQuarterlySales();
};
class CEO
{
private :
VicePresidentOfSales * m_vicePresidentOfSales;
public :
void increaseProfits(){
m_vicePresidentOfSales -> increaseQuarterlySales();
}
}
@interface Painter {}
-(void) painterCar : (Car) car;
@end
@interface PainterShopManager {}
Painter subPainter;
(-void) painterCar : (Car) car;
@end
@implementation PainterShopManager
(-void) paiterCar : (Car) car{
[subPainter painerCar : car];
}
@end
집단지성 엘리멘트 중에서.
1 : n(one to many) 관계의 데이터를 저장하는 자료구조
package util;
public interface IDataStore {
public int on(String $type, String $value);
public void off(String $type, Object $object);
public void off(String $type, int $id);
public void off(String $type);
public void off();
public void trigger(String $type, Object $object);
public void trigger(String $type);
}
어떤 특정한 스트링키에 매핑시킬 수 있는 여러 데이터를 가질 수 있는 자료구조예요.
상황에 따라 키가 스트링이 아닌 오브젝트로 바꿔서 사용해도 됩니다. 그럼 더욱 더 넓은 관계의 데이터 구조를 다룰 수 있게 되겠죠. 값이 아닌 키조차도 오브젝트형이라면.
내부적으론 자바의 Map과 배열리스트라는 자료를 응용해서 만든거구요.
C++의 STL을 사용하면 자바보다 훨씬 쉽게 구현할 수 있어요. STL은 구조체의 성격이라서 얼록이라는 과정이 필요없고 이 부분은 이런 자료구조의 로직에서 자바보다 더 쉬운 응용이 가능하더라구요. 그래서 쉬운 C++보다는 "아주 조금" 더 생각해야할 부분이 있는 자바로 구현했어요.
on이라는 메서드는 하나의 특정 키에 여러개의 값을 매핑할 수 있게 등록하는 기능을 가집니다.
off는 등록한 값을 지우는 기능을 하죠
trigger는 값을 꺼내는 역할을 합니당. 지금은 그냥 리턴 타입이 없게 만들어뒀어요.
테스트용에 불과하니까요 ㅎㅎ
package until;
import java.util.ArrayList;
import java.util.HashMap;
public class DataStore implements IDataStore{
private HashMap<String, ArrayList<Object>> index =
new HashMap<String, ArrayList<Object>>();
private static DataStore instance;
private DataStore(){}
public static DataStore sharedObject(){
if(instance == null){
instance = new DataStore();
}
return instance;
}
@Override
public int on(String $type, String $value) {
if(!this.index.containsKey($type)){
this.index.put($type, new ArrayList<Object>());
}
this.index.get($type).add($value);
return this.index.get($type).size();
}
@Override
public void off(String $type, Object $object) {
if(!this.index.containsKey($type)) return;
if(this.index.get($type).isEmpty()) return;
if(!this.index.get($type).contains($object)) return;
this.index.get($type).remove($object);
}
@Override
public void off(String $type, int $id) {
if(!this.index.containsKey($type)) return;
if(this.index.get($type).isEmpty()) return;
if($id >= this.index.get($type).size()) return;
this.index.get($type).remove($id);
}
@Override
public void off(String $type) {
if(!this.index.containsKey($type)) return;
if(this.index.get($type).isEmpty()) return;
this.index.get($type).clear();
}
@Override
public void off() {
this.index.clear();
}
@Override
public void trigger(String $type, Object $object) {
if(!this.index.containsKey($type)) return;
if(!this.index.get($type).contains($object)) return;
System.out.println($object);
}
@Override
public void trigger(String $type) {
if(!this.index.containsKey($type)) return;
for(int i=0; i<this.index.get($type).size(); ++i){
System.out.println(this.index.get($type).get(i));
}
}
}
로직을 보시면, 데이터 스토어는 맵을 갖고 있고 이 맵은 키에 매핑시킬 자료로 프리미티브값이 아닌 "배열"을 갖고 있어요.
on에서 데이터를 등록할 때, 연관키가 없을 경우에만 이 키에 대응시키는 배열을 얼록해주는 논리를 쓰고 있죠. 이 부분에서 STL보다는 살짝 더 고민을 해줘야하는 것 같아요. 얼록이라는 과정때문이죠.
테스트 코드는 아래와 같아요.
/* 데이터 스토어를 싱글턴 유형으로 생성 */
IDataStore dataStore = DataStore.sharedObject();
/* 객체에 사람이라는 키로 도킨스, 매트, 해리스를 저장 */
dataStore.on("사람", "도킨스");
dataStore.on("사람", "매트");
dataStore.on("사람", "해리스");
/* 객체에 동물이라는 키로 강아지, 고양이, 사자를 저장 */
dataStore.on("동물", "강아지");
dataStore.on("동물", "고양이");
dataStore.on("동물", "사자");
/* 사람이라는 키로 저장되어있는 모든 데이터를 출력 */
dataStore.trigger("사람");
System.out.println("----------");
/* 동물이라는 키로 저장되어있는 모든 데이터를 출력 */
dataStore.trigger("동물");
System.out.println("----------");
/* 사람이라는 키에서 john이라는 값을 지움.(그러나 john이라는 값이 저장되어 있지 않기 때문에 아무런 일도 발생하지 않음 */
dataStore.off("사람","john");
/* 사람이라는 키에서 해리스라는 값을 지움.(위에서 저장했던 해리스가 지워짐) */
dataStore.off("사람", "해리스");
/* 다시 출력. 사람이라는 키에서 해리스만 지워진것을 확인할 수 있음 */
dataStore.trigger("사람");
System.out.println("----------");
dataStore.trigger("동물");
System.out.println("----------");