Saturday, December 17, 2011

head first design pattern 2

  • Factory pattern
    • Factory method pattern : factory method pattern에서는 객체를 생성하기 위한 인터페이스를 정의하는데, 어떤 클래스의 인스턴스를 만들지는 서브클래스에서 결정하게 만든다. 팩토리 메소드 패턴을 이용하면 클래스의 인스턴스를 만드는 일을 서브클래스에게 맡기는 것이다.
    • abstract factory pattern : 추상 팩토리 패턴에서는 인터페이스를 이용하여 서로 연관된, 또는 의존하는 객체를 구상 클래스를 지정하지 않고도 생성할 수 있다.
    • factory method pattern은 상송을 통해서 객체를 만들고 abstract factory pattern은 객체 구성(interface의 구현)을 통해서 만든다. 
    • 예제 : PizzaStore을 예로 든다. factory method pattern 은 PizzaStore를 추상클래스로 만들어서 이 클래스의 추상 메소드를 derived class 들이 구현하게 한다. abstract factory pattern에서는 PizzaIngrediantFactory 라는 인터페이스를 만들어서 이를 정의 하는 구상 클래스를 만든다.  이때 PizzaStore의 derived class들은 각기 다른 PizzaIngrediantFactory를 맴버변수로 갖고 있어서 이 PizzaIngrediantFactory를 Pizza 객체를 만들때 인자로 넘겨준다. factory method pattern의 PizzaStore에서는 지역별 Pizza 클래스가 있어서 string(예를 들어 "cheese", "clam") 등을 인자로 넘기는데 반해 abstract factory pattern의 경우 지역별 Pizza 클래스가 있는것이 아니라 종류별 Pizza 클래스(예를 들어 "CheesePizza") 가 있어서 PizzaIngrediantFactory 객체를 인자로 넘긴다.
  • singleton pattern : 싱클턴 패턴은 해당 클래스의 인스턴스가 하나만 만들어지고, 어디서든지 그 인스턴스에 접근할 수 있도록 하기 위한 패턴이다.
    • 필요성 : 스레드 풀, 캐시, 대화상자, 사용자 설정, 레지스트리 설정등을 처리하는 객체는 여러개의 객체가 필요하지 않고 오히려 하나의 객체만 있어야 한다.
    • 단순 답변 : 생성자를 private로 하고 생성자를 호출하는 getInstance 라는 static 함수를 만들고 이 함수가 호출 되었을때 private로 되어 있는 생성자를 호출해서 자신의 객체를 만들고 이를 static 맴버 변수에다 넣어서 return 한다.
    • 문제점 : 멀티스레드에서 접근할 때 하나 이상의 객체가 생성될 가능성이 여전히 존재
    • singleton pattern : 1. getInstance 메소드 자체를 synchromized 키워드를 이용해서 동기화 한다. 혹은 2.static 맴버 변수에다가 프로그램이 시작 하자마자 클래스 객체를 생성해서 집어 넣는다. 혹은 3. DCL(double-checking locking)을 사용한다. 
  • command pattern : 커맨드 패턴을 이용하면 요구 사항을 개체로 캡슐화 할 수 있으며, 매개변수를 써서 여러 가지 다른 요구 사항을 집어넣을 수도 있다. 또한 요청 내역을 큐에 저장하거나 로그로 기록할 수도 있으며, 작업취소 기능도 지원 가능하다.
    • 예제 : 특정 리모컨이 있는데 여기에는 10개의 슬롯이 있고 각 슬롯에는 on/off 스위치가 두개씩 있다. 그리고 undo 라는 스위치가 하나 있다. 이 리모컨을 만능 리모콘이 되도록 코딩한다. 그러니까 어떤 슬롯은 형광등의 스위치 버튼이 되고 어떤 슬롯은 자동문의 버튼이 되는 것. 문제는 어떤 슬롯이 어떤 일을 할지 모른다는것. 결국 필요한건 메소드의 캡슐화
    • command pattern : client는 receiver를 command 객체에 넣어서 이 command 객체를 invoker에게 넘기면 invoker는 command 객체를 실행 시킨다. command 는 interface 이고 execute라는 virtual 함수가 있고 이를 구현한 구상 객체들이 존재한다. 실질적으로 이 구상 객체들이 execute 라는 함수를 구현한다. 이 execute 함수 안에 각 command가 구성 객체로 받는 receiver들의 함수들을 호출하는 것이다. 결국 invoker는 command를 받아서 command 객체의 execute 만 실행 할 뿐 어떤 메소들이 실행되는지는 알 수가 없다. 위 예제를 비유하자면 client는 리모컨을 사용하는 사람이 되겠고 invoker가 리모컨, receiver가 리모컨이 컨트롤 하는 각종 기기들의 function을 정의한 클래스가 되겠고, command는 단지 리모컨의 메소드 캡슐화를 위한 실제적인 receiver 핸들 객체가 되겠다.