OOP 설계 5원칙

from Ooad 2010/07/19 16:59
소프트웨어 공학시간에 배우게 되는 5개의 설계 원칙에 대한 내용입니다.

1. 단일 책임의 원칙(SRP : Single Responsibility Principle)
- 한 객체는 하나의 책임을 져야 한다는 원칙으로 높은 응집도와 낮은 결합도를 기본으로 하고 있다.

2. 의존 관계 역전의 법칙(DIP : Dependency Inversion Principle)
- 클라이언트는 상세 클래스가 아닌 추상화(인터페이스, 추상클래스) 레이어에 의존해야 한다는 원칙으로, 확장 이슈가 있는 부분은 부분은 추상화를 해야 된다는 내용입니다. 

3. 인터페이스 분리의 원칙(ISP : Interface Segregation Principle)
- 클라이언트에 특화된 여러개의 인터페이스가 하나의 범용 인터페이스보다 낫다

4. 리스코프 대체 원칙(LSP : Liskov Substitution Principle)
- 상위 클래스는 파생클래스로 대체 가능해야 되는 원칙으로, 기반클래스의 기능은 파생클래스가 포함을 해야 된다는 내용입니다. 따라서, 파생클래스는 상위클래스보다 더 많은 기능을 제공을 하게 되겠습니다.  아래의 lsp.doc 파일은 전에 스터디를 하면서, C#으로 만들어본 예제입니다.

5. 개방 폐쇄 원칙(Open-Closed Principle)
- 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다는 원칙으로 기존의 클래스에 수정하지 말고, 상속 또는 구현으로 확장을 해야 된다는 내용입니다.

'Ooad' 카테고리의 다른 글

OOP 설계 5원칙  (2) 2010/07/19
Singleton Pattern  (0) 2010/04/29
Null Object Pattern  (2) 2009/09/17
Specification Pattern  (2) 2009/09/16
디자인 패턴 그리고 그 이후..  (0) 2009/09/16

Singleton Pattern

from Ooad 2010/04/29 16:34
아래 내용은 OKJSP에서 발췌를 하였습니다..
소스코드내에는 몇가지 싱글톤 구현방법이 나옵니다. 그 각각이 의미하는바는 다음과 같습니다.

1) EagerSingleton
static class EagerSingleton extends Singleton {
    static final EagerSingleton theInstance = new EagerSingleton();
    static EagerSingleton getInstance() {
        return theInstance;
    }
}
이 경우는 미리 싱글톤 인스턴스를 생성하는 방법으로 static final 필드에 인스턴스를 생성하여 할당하는 방법입니다. 이 필드는 클래스로더에 의해서 EagerSingleton이 메모리로 올라오는 순간에 안전하게(thread-safe하게)초기화 됩니다. 이 방법이 아마 성능이 가장 우수하게 나타날 것입니다.
장점은 동기화부담이 적다는 것입니다. 단 한번 클래스로더가 thread-safe하게 클래스를 로드하는 시점에 클래스가 로딩되어 안전합니다. 단점은 인스턴스가 미리부터 생성된다는 것입니다.

2) SynchedSingleton
static class SynchedSingleton extends Singleton {
    static SynchedSingleton theInstance;
    static synchronized SynchedSingleton getInstance() {
        if (theInstance == null)
            theInstance = new SynchedSingleton();
        return theInstance;
    }
}
이 방법은 싱글톤 필드에 접근할때마다 동기화를 수행하는 방법입니다. 매번 동기화를 수행하므로 자바 메모리 모델에 따른 각종 문제를 방지할 수 있어 thread-safe합니다. 단점은 매번동기화를 수행하므로 수행 비용이 높다는 것입니다.

3) ThreadLocalSingleton
static class ThreadLocalSingleton extends Singleton {
    static final ThreadLocal perThreadInstance = new ThreadLocal();
    static final Object lock = new Object();
    static ThreadLocalSingleton theInstance;
    static ThreadLocalSingleton getInstance() {
        ThreadLocalSingleton instance = (ThreadLocalSingleton)(perThreadInstance.get());
        if (instance == null) {
            synchronized(lock) {
                instance = theInstance;
                if (instance == null)
                    instance = theInstance = new ThreadLocalSingleton();
            } // copy global to per-thread
                perThreadInstance.set(instance);
        }
        return instance;
    }
}
이 방법은 Thread Local Storage를 사용한 해법입니다. 자바 쓰레드 메모리 모델에서 문제가 발생하는 것은 멀티 CPU상황에서 각각의 CPU가 자신의 캐시내에 클래스의 필드를 복사해넣는다는 것입니다. 이러한 캐시는 메인메모리와 동기화가 되어 있지 않습니다. 즉, 각각의 CPU가 하나의 클래스를 접근하게되면 각각의 CPU는 그 클래스의 내용을 다르게 볼 수 있다는 것입니다.
싱글톤을 구현하면 instance라는 필드를 여러개의 CPU가 참조하는데 이 필드를 여러개의 CPU가 다르게 보게 됩니다. 예를들어 CPU A가 인스턴스를 생성하고 생성한 인스턴스를 instance에 할당한다고 합시다.
그러면 CPU A가 또다시 이 instance 필드를 참조할때는 생성된 인스턴스를 제대로 보게 됩니다. 그러나 CPU B가 이 instance필드를 참조할때는 instance필드가 null로 나타날 수 있습니다. 그 이유는 CPU A가 수행한 작업은 synchronized블록을 통과할때까지 메인메모리에 반영이 안되고 자신의 캐시내에만 담겨 있을 수 있으며, CPU B역시 synchornized블록을 통과하지 않으면 메인메모리가 아닌 자신의 캐시만
들여다보기 때문입니다.

이를 해결하려면 각각 CPU가 동기화블록을 들어갔다가 나와야만 하는데, 이를 구현한 것이 위의 코드입니다. 각각의 Thread는 자신만의 메모리공간으로서 TLS(Thread Local Storage)를 가지고 있으며 이들은 매 쓰레드마다의 공간이므로 동기화될 필요가 없습니다. 따라서 이 저장소에 해당 쓰레드가 synchronized블록을 한번이라도 다녀왔는지(한번이라도 다녀오면 CPU가 메인메모리의 값을 가져오니까요)를
저장해둡니다.

4) SimulatedThreadLocalSingleton
static class SimulatedThreadLocalSingleton extends Singleton {
    static SimulatedThreadLocalSingleton theInstance;
    static final Object lock = new Object();
    static final Object key = new Object();
    static Singleton getInstance() {
        TSS t = (TSS)(Thread.currentThread());
        Singleton instance = (Singleton)(t.threadLocalHashtable.get(key));
        if (instance == null) {
            synchronized(lock) {
                instance = theInstance;
                if (instance == null)
                    instance = theInstance = new SimulatedThreadLocalSingleton();
            } // copy global to per-thread
            t.threadLocalHashtable.put(key, instance);
        }
        return instance;
    }
}
이 방법은 TLS를 ThreadLocal 클래스를 쓰지 않고 직접구현한 방식입니다.

5) VolatileSingleton
static class VolatileSingleton extends Singleton {
    static final Object lock = new Object();
    static volatile VolatileSingleton theInstance;
    static VolatileSingleton getInstance() {
        VolatileSingleton instance = theInstance;
        if (instance == null) {
            synchronized(lock) {
                instance = theInstance;
                if (instance == null)
                    instance = theInstance = new VolatileSingleton();
            }
        }
    return instance;
    }
}
주의!)이 방법은 절대로 사용해서는 안됩니다.

이 방법은 volatile를 사용합니다. volatile 로 선언된 필드는 매번 원자적으로 쓰레드 safe하게 이루어집니다. 즉 각각의 변수에 대한 접근이 매번 메인메모리와 동기화될 뿐만아니라, thread safe하게 이루어집니다. synchronized와 volatile은 이처럼 변수의 접근마다 동기화를 하느냐 아니면 특정 블록을 통채로 동기화 하는냐의 문제에 있어서 접근방법이 틀립니다. 그러나 아쉽게도 volatile은 대부분의 자바 컴파일러에서 제대로 구현되어있지않으며 따라서 사용하는것을 권하지 않습니다. SUN의 컴파일러는 제대로 되지 않느냐 하고 생각하실 수 있지만 전혀 안그렇습니다. SUN의 JDK 1.3대에서도 제대로 구현이 되어있지 않습니다.
volatile은 동기화의 문제를 비롯한 다양한 암시적 작동이 보장되어야하는데 이를 제대로 책임지고 않기때문입니다.

6) DirectThreadFieldSingleton
static class DirectThreadFieldSingleton extends Singleton {
    static DirectThreadFieldSingleton theInstance;
    static final Object lock = new Object();
    static Singleton getInstance(TSS t) {
        Singleton instance = t.singleton;
        if (instance == null) {
            synchronized(lock) {
                instance = theInstance;
                if (instance == null)
                instance = theInstance = new DirectThreadFieldSingleton();
            } // copy global to per-thread
            t.singleton = instance;
        }
        return instance;
    }
}
인스턴스를 할당받고자하는 쪽에서 TSS라는 형태의 클래스를 쓰레드마다 할당한채로 갖고 있다가 이것을 싱글톤 클래스에 넘깁니다. 그러면 TSS.singleton변수의 값을가지고 동기화 수행여부를 결정하는 방식입니다. ThreadLocal의 변형이며, 모든 인스턴스를 획득하고자하는 쓰레드가 TSS를 넘겨야한다는 점에서
좋은 방법은 아니겠죠.

7) ThreadFieldSingleton
static class ThreadFieldSingleton extends Singleton {
    static final Object lock = new Object();
    static ThreadFieldSingleton theInstance;
    static Singleton getInstance() {
        TSS t = (TSS)(Thread.currentThread());
        Singleton instance = t.singleton;
        if (instance == null) {
            synchronized(lock) {
                instance = theInstance;
                if (instance == null)
                    instance = theInstance = new ThreadFieldSingleton();
            } // copy global to per-thread
            t.singleton = instance;
        }
        return instance;
    }
}
이 방법역시 ThreadLocal의 구현에 대한 변형된 구현입니다. ThreadLocal 대신, 특정 싱글톤 클래스에 대한 인스턴스를 획득하려고 시도하는 쓰레드를 캐스팅해서 ThreadLocal을 구현한 것이죠. 개인적으로 이 방법은 별로 좋지 않다고봅니다. 특정 클래스의 인스턴스를 획득하려면 쓰레드가 어떠한 인스턴스를 구현하고 있는지는 쉽사리 가정하기가 곤란하죠.


'Ooad' 카테고리의 다른 글

OOP 설계 5원칙  (2) 2010/07/19
Singleton Pattern  (0) 2010/04/29
Null Object Pattern  (2) 2009/09/17
Specification Pattern  (2) 2009/09/16
디자인 패턴 그리고 그 이후..  (0) 2009/09/16

Null Object Pattern

from Ooad 2009/09/17 17:35
Null Object Pattern 또는 Null Object라고 하는 내용은 NullReference를 방지하기 위해서 더미(?) 객체를 미리 만들어 넣고 기능을 제공하는 핸들러에 바인딩 되어 있는 타입의 객체(실 기능 구현 객체)가 널인지를 체크해서 NullPointerException을 방지하기 위한 패턴이더군요.. 마틴 파울러님의 Introduce Null Object에서도 동일한 내용이 나옵니다...
한글로 설명하는 것보다, 코드로 보면 더 간단하게 보실 수 있습니다.

예제에서의 핵심은 이 코드입니다..
 /**
  * return logger
  * @return
  */
 public ILogger getLogger() {
  if(this.logger == null)
   return NullLogger.getInstance();
  
  return this.logger;
 }


아래는 로그를 남기는 예제코드입니다.

package net.sjava.patterns.nullobject;

/**
 *
 * @author mcsong@gmail.com
 * @since 2009. 9. 17.
 */
public interface ILogger {
 
 /**
  *
  * @param log
  */
 public void log(String log);
}

 

package net.sjava.patterns.nullobject;

/**
 *
 * @author mcsong@gmail.com
 * @since 2009. 9. 17.
 */
public class FileLogger implements ILogger {

 @Override
 public void log(String log) {
  System.out.println("file log - " + log);
 }
}

 

package net.sjava.patterns.nullobject;

/**
 *
 * @author mcsong@gmail.com
 * @since 2009. 9. 17.
 */
public class NullLogger implements ILogger {
 
 /**
  * singleton instance
  */
 private static final NullLogger instance = new NullLogger();

 /**
  *
  */
 private NullLogger() {
 
 }

 /**
  * return singleton instance
  * @return
  */
 public static NullLogger getInstance() {
  return NullLogger.instance;
 }
 
 @Override
 public void log(String log) {
  // TODO Auto-generated method stub
  System.out.println("null log - " + log);
 }
}

 

package net.sjava.patterns.nullobject;

/**
 *
 * @author mcsong@gmail.com
 * @since 2009. 9. 17.
 */
public class SocketLogger implements ILogger {

 @Override
 public void log(String log) {
  // TODO Auto-generated method stub
  System.out.println("socket log - " + log);
 }
}

 

package net.sjava.patterns.nullobject;

/**
 *
 * @author mcsong@gmail.com
 * @since 2009. 9. 17.
 */
public class LoggerHandler {

 /**
  * type
  */
 private ILogger logger;
 
 /**
  * constructor
  * @param logger
  */
 public LoggerHandler(ILogger logger) {
  this.logger = logger;
 }
 
 /**
  * return logger
  * @return
  */
 public ILogger getLogger() {
  if(this.logger == null)
   return NullLogger.getInstance();
  
  return this.logger;
 }
 
 /**
  *
  * @param log
  */
 public void log(String log) {
  this.getLogger().log(log);
 }
 
 /**
  *
  * @param logger
  * @param log
  */
 public void log(ILogger logger, String log) {
  this.logger = logger;
  this.log(log);
 }
}

 

import net.sjava.patterns.nullobject.FileLogger;
import net.sjava.patterns.nullobject.SocketLogger;
import net.sjava.patterns.nullobject.LoggerHandler;

public class NullObjectTest {
 /**
  * handler
  */
 private static LoggerHandler handler;
  
 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  
  handler = new LoggerHandler(null);
  handler.log("fileloggger");

  handler = new LoggerHandler(new FileLogger());
  handler.log("socketloggger");
  
  handler = new LoggerHandler(new SocketLogger());
  handler.log("socketloggger");
 }
}


'Ooad' 카테고리의 다른 글

OOP 설계 5원칙  (2) 2010/07/19
Singleton Pattern  (0) 2010/04/29
Null Object Pattern  (2) 2009/09/17
Specification Pattern  (2) 2009/09/16
디자인 패턴 그리고 그 이후..  (0) 2009/09/16

Specification Pattern

from Ooad 2009/09/16 15:24

위키피디아에 한 마디로 "Recombinable business logic in a boolean fashion" 이라고 나와 있습니다.

위키피디아의 한 마디는, 비지니스 로직 처리를 하기 위해서 if~else를 보통 많이 쓰는데, 그 if~else를 제거하고 비지니스 로직을 확장에 쉽게 Composition하는 패턴이라고 설명을 하는 것 이겠지요??
그리고, 로직이 다른 클래스가 하위 클래스로 점진적으로 추가 된다면, Strategy Pattern과 유사한 형태가 될 것 같습니다. 하지만, Strategy Pattern은 데이타에 대한 처리나 체크를 Concrete Strategy에서 하고 Specification Pattern은 모델의 Provider 클래스가 처리를 대행하는 형태라는게 다른 것 같습니다.

아래 링크도 참고하시면 좋을 듯 합니다.
http://en.wikipedia.org/wiki/Specification_pattern#C.23
http://decoder.tistory.com/877

아래는 예제 코드 입니다...

package net.sjava.patterns.specification;

/**
 *
 * @author mcsong@gmail.com
 * @since 2009. 9. 16.
 */
public class User {
 /**
  * name
  */
 private String name;
 
 /**
  * city
  */
 private String city;
 /**
  * address
  */
 private String address;
 /**
  * company
  */
 private String companyName;
 
 /**
  * @return the name
  */
 public String getName() {
  return name;
 }
 /**
  * @param name the name to set
  */
 public void setName(String name) {
  this.name = name;
 }
 /**
  * @return the city
  */
 public String getCity() {
  return city;
 }
 /**
  * @param city the city to set
  */
 public void setCity(String city) {
  this.city = city;
 }
 /**
  * @return the address
  */
 public String getAddress() {
  return address;
 }
 /**
  * @param address the address to set
  */
 public void setAddress(String address) {
  this.address = address;
 }
 /**
  * @return the company
  */
 public String getCompanyName() {
  return companyName;
 }
 /**
  * @param company the company to set
  */
 public void setCompanyName(String company) {
  this.companyName = company;
 }
}

 

package net.sjava.patterns.specification;

/**
 *  
 * @author mcsong@gmail.com
 * @since 2009. 9. 16.
 */
public interface IUserSpecification {
 /**
  *
  * @param user
  * @return
  */
 public boolean isSatisfied(User user);
}

 

package net.sjava.patterns.specification;

/**
 *
 * @author mcsong@gmail.com
 * @since 2009. 9. 16.
 */
public abstract class AbstractUserSpecification implements IUserSpecification {
 
 @Override
 public boolean isSatisfied(User member) {
  // TODO Auto-generated method stub
  return true;
 }
}

 

package net.sjava.patterns.specification;

/**
 *
 * @author mcsong@gmail.com
 * @since 2009. 9. 16.
 */
public class CompanySpecification extends AbstractUserSpecification {

 /**
  *
  */
    private String companyName;
   
    /**
     *
     * @param companyName
     */
    public CompanySpecification(String companyName)
    {
        this.companyName = companyName;
    }
 
 @Override
 public boolean isSatisfied(User user) {
  // TODO Auto-generated method stub
  if(user == null)
   return false;
  
  return user.getCompanyName().equals(this.companyName);
 }
}

 

package net.sjava.patterns.specification;

import java.util.ArrayList;

/**
 *
 * @author mcsong@gmail.com
 * @since 2009. 9. 16.
 */
public class UserProvider {
 
 /**
  *
  */
 private static ArrayList<User> users = new ArrayList<User>();
 
 /**
  *
  */
 private static java.util.concurrent.atomic.AtomicBoolean isLoaded = null;
 
 
 /**
  *
  */
 private UserProvider() {
  if(isLoaded == null) {
   isLoaded = new java.util.concurrent.atomic.AtomicBoolean();
   UserProvider.isLoaded.set(true);
   UserProvider.provideUsers();
    
  }
 }

 /**
  *
  * @return
  */
 public static UserProvider provider() {
  return new UserProvider();  
 }
 
 /**
  * dummy data 입력
  */
 public static void provideUsers() {
  
  for(int i=0; i < 10; i++) {
   User user = new User();
   user.setName(String.valueOf(i));
   user.setCity("서울");
   user.setAddress(String.valueOf(i) + " 번지");
   if(i < 5)
    user.setCompanyName("회사");
   else
    user.setCompanyName("백수");
   
   users.add(user);
  }
 }
 
 /**
  *
  * @param user
  * @return
  */
 public ArrayList<User> getSpecificationList(IUserSpecification specification) {
  
  ArrayList<User> list = new ArrayList<User>();
 
  for(int i=0; i < users.size(); i++) {
   if(specification.isSatisfied(users.get(i)))
    list.add(users.get(i));
  }
        return list;
    }

}

 

import java.util.ArrayList;
import net.sjava.patterns.specification.User;
import net.sjava.patterns.specification.UserProvider;
import net.sjava.patterns.specification.IUserSpecification;
import net.sjava.patterns.specification.CompanySpecification;


public class SpecificationPatternTest {

 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  ArrayList<User> users = null;
  IUserSpecification spec = null;
  
  spec = new CompanySpecification("회사");
  users = UserProvider.provider().getSpecificationList(spec);
  
  for(int i=0; i < users.size(); i++) {
   System.out.println(i + users.get(i).getCompanyName());
  }
  
  spec = new CompanySpecification("백수");
  users = UserProvider.provider().getSpecificationList(spec);
  
  for(int i=0; i < users.size(); i++) {
   System.out.println(i + users.get(i).getCompanyName());
  }
 }
}

'Ooad' 카테고리의 다른 글

Singleton Pattern  (0) 2010/04/29
Null Object Pattern  (2) 2009/09/17
Specification Pattern  (2) 2009/09/16
디자인 패턴 그리고 그 이후..  (0) 2009/09/16
OOP에 대한 내용들..  (0) 2009/07/06
몇일전에 에릭감마의 내한 세미나에 참석을 하였습니다.
거기서, 에릭감마는 디자인 패턴이 지금은 구식이 되어 버린 경우가 생겼고, 그것에 대한 계속적인 스터디가 필요하다고 말했던 것으로 기억을 하고 있습니다(아님 말고.. ^^;;).

위의 상황에 대한 적절한 스터디를 할 수 있는 곳이 있더군요.. ^^
아 좋네요.. concurreny에 대한 내용도 있고..

http://en.wikipedia.org/wiki/Software_design_pattern

'Ooad' 카테고리의 다른 글

Null Object Pattern  (2) 2009/09/17
Specification Pattern  (2) 2009/09/16
디자인 패턴 그리고 그 이후..  (0) 2009/09/16
OOP에 대한 내용들..  (0) 2009/07/06
단순 Reactor 패턴의 성능향상 방안..  (0) 2009/06/25

OOP에 대한 내용들..

from Ooad 2009/07/06 10:30
OOP란 조건문(if)을 줄이는 것

정말 다형성(서브타입)이 IF를 줄일수 있을까?

객체지향 프로그래밍에 대한 오해와 진실 I

객체지향 프로그래밍에 대한 오해와 진실 II

'Ooad' 카테고리의 다른 글

Specification Pattern  (2) 2009/09/16
디자인 패턴 그리고 그 이후..  (0) 2009/09/16
OOP에 대한 내용들..  (0) 2009/07/06
단순 Reactor 패턴의 성능향상 방안..  (0) 2009/06/25
DI(Dependency Injection)에 대해서..  (0) 2009/06/25
Tag // ooad, OOP

Reactor 패턴을 이용해서 자바로 네트워크 서버를 개발하다 보면, 하나의 Reactor로는 고 성능이 아니더라도 동접을 2000 이상 붙여보면 성능저하를 눈으로 확인해 볼 수 있습니다.. 그래서 Reator를 Master-Slave의 형태와 Slave Reactor를 cpu 갯수만큼 만들어서 성능을 높일 수 있습니다. 그러한 구조를 한눈에 알 수 있게 보여주는 그림입니다.. ^^





 

'Ooad' 카테고리의 다른 글

디자인 패턴 그리고 그 이후..  (0) 2009/09/16
OOP에 대한 내용들..  (0) 2009/07/06
단순 Reactor 패턴의 성능향상 방안..  (0) 2009/06/25
DI(Dependency Injection)에 대해서..  (0) 2009/06/25
POSA 1 - Master-Slave Pattern  (0) 2009/06/18

객체가 스스로 참조하는 객체를 생성하지 않고, 외부 환경(컨테이너)에서 삽입 되는 형태를 DI(Dependency Injection)라고 하네요.. ^^

DI 를 구현하는 방법은 2가지가 있네요..

1. Constructor 방식

public class Shop {  
  private final StockManager stockManager;  
  private final String shopZipCode;  
  public Shop(StockManager stockManager, String shopZipCode) {  
       this.stockManager = stockManager;  
       this.shopZipCode = shopZipCode;  
  }  
}

2. Setter 방식

public class Shop {  
  StockManager stockManager;  
  String shopZipCode;  
  /** 
  * @service name="StockManager"      
  */ 
  public void setStockManager(StockManager stockManager) {  
      this.stockManager = stockManager;  
  }  
  /** 
  * @config name="shopZipCode"      
  */ 
  public void setStockManager(String shopZipCode) {  
      this.shopZipCode= shopZipCode;  
  }  
  // TODO - Joe - how does setter injector do config ? Same way?  
  public void initialize() {  
      // all setXXXs are now done :-)  
  }  


위 내용은 http://www.picocontainer.org/injection.html 에서 읽어보시면 도움이 될것 같습니다. ^^

'Ooad' 카테고리의 다른 글

OOP에 대한 내용들..  (0) 2009/07/06
단순 Reactor 패턴의 성능향상 방안..  (0) 2009/06/25
DI(Dependency Injection)에 대해서..  (0) 2009/06/25
POSA 1 - Master-Slave Pattern  (0) 2009/06/18
POSA 1 - Whole-Part Pattern  (0) 2009/06/16

POSA 1 - Master-Slave Pattern

from Ooad 2009/06/18 11:24
Master-Slave Pattern은 Master가 Slave에게 작업을 분산하고, Slave를 통해서 받은 결과를 통해서 최종 결과를 계산해 내는 패턴이라고 하네요.. 따라서, Master는 작업을 쪼개고, Slaver에게 분배하고, 결과를 계산하는 역할을 할 것이고, Slave는 Master의 작업요청을 처리해서 결과를 리턴하면 되겠네요..

제가 생각하는 내용을 아래의 형태별로 간단하게 코드로 끄적여 봅니다.
예는 1부터 10까지의 factorial을 10개의 Job으로 나누고, 그것을 Master가 더하기를 합니다.
아래의 MSClient는 Client와 Master의 역할을 담당하게 되고, JobThread는 Slave의 역할을 담당합니다.
혹시 코드보시고, 틀렸다고 생각이 되시는 부분이 있으면 답글로 끄적여 주시면 감사하겠습니다.

MSClient.java
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.Future;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ExecutionException;
import java.math.BigInteger;

public class MSClient {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
           
        ArrayList<JobThread> jobArray = new ArrayList<JobThread>();
        ExecutorService executor =  Executors.newFixedThreadPool(10);
           
        for (int i = 1; i <= 10; i++) {
            jobArray.add(new JobThread(i));
        }
       
        List<Future<BigInteger>> allResults = null;
       
        long totalSum = 0;
       
        try {
            allResults = executor.invokeAll(jobArray);
                         
            for(int i=0; i < allResults.size(); i++) {
                totalSum += allResults.get(i).get().longValue();
                System.out.println((i+1) + "! is " + allResults.get(i).get());
            }
           
            System.out.println("Total Value is " + totalSum);

        } catch (InterruptedException e) {
            System.out.println("Interrupted");
        } catch (ExecutionException e) {
            System.out.println( "Execution exception");
        }
       
        executor.shutdown();
    }
}


JobThread.java
import java.util.concurrent.Callable;
import java.math.BigInteger;

public class JobThread implements Callable<BigInteger> {
    //
    private int min = 1;
    //
    private int value = 0;
   
    public JobThread(int value) {
        this.value = value;
    }
   
    @Override
    public BigInteger call() throws Exception {
       
        BigInteger fac = BigInteger.valueOf(this.min);
       
        for (int i = 1; i <= this.value; i++)
            fac = fac.multiply(BigInteger.valueOf(i));
   
        return fac;
    }
}

* reference
- http://www.devpia.com/NET2/EvaCast/Lecture/?cu=view&r=105

POSA 1 - Whole-Part Pattern

from Ooad 2009/06/16 17:45
Whole-Part 패턴은 Whole 객체를 구성하는 Part 객체들을 모으고, 그 객체들간의 협력을 통해서 기능을 구현하는 패턴입니다. 그리고, Whole 객체가 클라이언트에 인터페이스를 제공하고 Part 객체들은 Whole객체만을 통해서 접근을 하게 만들어 주는 형태입니다. GOF의 Composite 패턴과 동일한 느낌이네요.. ^^;;

제가 생각하는 내용을 아래의 형태별로 간단하게 코드로 끄적여 봅니다.
아래의 WPClient는 Car라는 Whole 객체를 통해서 앞으로 뒤로 기능을 테스트 합니다.
혹시 코드보시고, 틀렸다고 생각이 되시는 부분이 있으면 답글로 끄적여 주시면 감사하겠습니다.

WPClient.java
package client;

import wp.Car;
import wp.part.*;

public class WPClient {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Car car = new Car();
        car.setEngine(new Engine());
        car.setLight(new Light());
        car.setWheel(new Wheels());
       
        car.keyPress(true);
        car.forward();
        car.backward();
    }
}

Car.java
package wp;

import wp.part.*;

public class Car {
    //
    private Wheels wheel;
    //
    private Engine engine;
    //
    private Light light;
   
    public Wheels getWheel() {
        return wheel;
    }
    public void setWheel(Wheels wheel) {
        this.wheel = wheel;
    }
    public Engine getEngine() {
        return engine;
    }
    public void setEngine(Engine engine) {
        this.engine = engine;
    }
    public Light getLight() {
        return light;
    }
    public void setLight(Light light) {
        this.light = light;
    }
   
    public void keyPress(boolean isNight) {
        boolean check = false;
       
        check = this.engine.start();
        if(isNight) {   
            check = this.light.start();
        }
    }

    public void forward() {
        boolean check = this.wheel.forward();
       
    }
   
    public void backward() {
        boolean check = this.wheel.backward();
    }
}

Engine.java
package wp.part;

public class Engine {
   
    private boolean isStarted;
   
    public boolean start() {
        System.out.println("Engine start Ok");
        this.isStarted = true;
        return true;
    }
   
    public void stop() {
        this.isStarted = false;
    }
}

Light.java
package wp.part;

public class Light {
    private boolean isLighting;
   
    public boolean start() {
        System.out.println("Light start Ok");
        this.isLighting = true;
        return true;
    }
   
    public void stop() {
        this.isLighting = false;
    }
}

Wheels.java
package wp.part;

public class Wheels {

    private boolean isWheeling;
   
    public boolean forward() {
        System.out.println("앞으로 굴러갑니다.");
        this.isWheeling = true;
        return true;
    }
   
    public boolean backward() {
        System.out.println("뒤로 굴러갑니다.");
        this.isWheeling = true;
        return true;
    }
   
    public void stop() {
        this.isWheeling = false;
    }
}

* reference
- http://www.devpia.com/NET2/EvaCast/Lecture/?cu=view&r=128
- http://wiki.javajigi.net/display/SWD/Whole-Part+Design+Pattern

'Ooad' 카테고리의 다른 글

DI(Dependency Injection)에 대해서..  (0) 2009/06/25
POSA 1 - Master-Slave Pattern  (0) 2009/06/18
POSA 1 - Whole-Part Pattern  (0) 2009/06/16
POSA 1 - Presentation Abstraction Control Pattern  (0) 2009/06/15
POSA 1 - Layers Pattern  (0) 2009/06/09

Presentation Abstraction Control Pattern은 계층 형태의 시스템에서 각 단계별로 Agent를 가지고, Agent들이 계층적(상,하)으로 협력을 하는 구조가 필요할 때 사용할 수 있는 패턴이라고 하네요.. 각 Agent는 계층의 레벨에 맞는 기능을 담당합니다. 그리고 각 Agent는 Presentation, Abstraction, Control을 가질 수 있습니다.

제가 생각하는 내용을 아래의 형태별로 간단하게 코드로 끄적여 봅니다.
아래의 TopAgent는 데이타를 가지고 있고, InterMediateAgent는 mediate 기능을 담당하고 실제로 뷰는 BottomAgent를 통해서 구현을 합니다. 그리고, BottomAgent는 view()는 인터페이스로 뽑고, setter, getter 메쏘드는 Abstract Class를 통해서 여러개의 BottomAgent를 구현하면 좋을듯 합니다.

혹시 코드보시고, 틀렸다고 생각이 되시는 부분이 있으면 답글로 끄적여 주시면 감사하겠습니다

PACClient.java

public class PACClient {

 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  
  pac.TopAgent tAgent = new pac.TopAgent();
  pac.inter.InterMediateAgent interAgent = new pac.inter.InterMediateAgent();
  pac.bottom.BottomAgent bAgent = new pac.bottom.BottomAgent();
  
  interAgent.setTopAgent(tAgent);
  bAgent.setIntermediateAgent(interAgent);
  interAgent.setBottomAgent(bAgent);
  
  interAgent.sendMsg();
 }
}

TopAgent.java

package pac;

import pac.inter.InterMediateAgent;

public class TopAgent {
 //
 private InterMediateAgent intermediateAgent = null;
 
 private String data = null;
 
 //
 public InterMediateAgent getIntermediateAgent() {
  return intermediateAgent;
 }

 //
 public void setIntermediateAgent(InterMediateAgent agent ) {
  intermediateAgent = agent;
 }
 
 @SuppressWarnings("deprecation")
 public String getData() {
  this.data = "loading data "
   + new java.util.Date().getYear() +", "
   + new java.util.Date().getMonth() +", "
   + new java.util.Date().getDay() +", "
   + new java.util.Date().getHours() +", "
   + new java.util.Date().getMinutes() +", "
   + new java.util.Date().getSeconds();
  
  return this.data;
 }

 //
 public void setData(String data) {
  this.data = data;
 }
}



InterMediateAgent.java

package pac.inter;

import pac.TopAgent;
import pac.bottom.BottomAgent;

public class InterMediateAgent {
 //
 private TopAgent topAgent = null;

 //
 private BottomAgent bottomAgent = null;
 
 //
 public TopAgent getTopAgent(){
  return topAgent;
 }

 //
 public void setTopAgent(TopAgent agent){
  topAgent = agent;
 }
 
 //
 public BottomAgent getBottomAgent(){
  return bottomAgent;
 }
 
 //
 public void setBottomAgent(BottomAgent agent){
  bottomAgent = agent;
 }
 
 //
 public String getData() {
  return this.topAgent.getData();
 }
 
 //
 public void SetData(String data) {
  this.topAgent.setData(data);
 }
 
 // template method가 되도 되겠넹..
 public void sendMsg() {
  this.bottomAgent.view();
 }

}

BottomAgent.java

package pac.bottom;

import pac.inter.InterMediateAgent;

public class BottomAgent { 
 //
 private InterMediateAgent interAgent = null;
 
 //
 private Abstraction abs = null;

 //
 private Presentation pre = null;
 
 //
 public BottomAgent() {
  abs = new Abstraction();
  pre = new Presentation();
 }
 
 //
 public InterMediateAgent getIntermediateAgent() {
  return interAgent;
 }

 //
 public void setIntermediateAgent(InterMediateAgent agent) {
  this.interAgent = agent;
 }
 
 //
 public void view() {
  String source = this.interAgent.getData();
  abs.setData(source);
  
  pre.view(abs.getData());
 }
}



Abstraction.java

package pac.bottom;

public class Abstraction {
 //
 private String data;
 
 public String getData() {
  return data;
 }

 public void setData(String data) {
  this.data = data;
 }
 
 //
 public String toString() {
  return data;
 }
}



Presentation.java

package pac.bottom;

public class Presentation {
 String data = null;
 
 public String getData() {
  return data;
 }

 public void setData(String data) {
  this.data = data;
 }


 public void view(Object obj) {
  System.out.println(obj.toString());
 }
}


* reference
http://en.wikipedia.org/wiki/Presentation-abstraction-control
- http://www.devpia.com/net2/EvaCast/Lecture/?cu=view&r=126
- http://lakhos.egloos.com/2771689
 

'Ooad' 카테고리의 다른 글

POSA 1 - Master-Slave Pattern  (0) 2009/06/18
POSA 1 - Whole-Part Pattern  (0) 2009/06/16
POSA 1 - Presentation Abstraction Control Pattern  (0) 2009/06/15
POSA 1 - Layers Pattern  (0) 2009/06/09
POSA 2 - A System of Patterns  (0) 2008/07/28

POSA 1 - Layers Pattern

from Ooad 2009/06/09 17:00
간단하게 말하면 복잡한 시스템을 레이어로 나눠서 Task를 하위 레이어 또는 상위 레이어로의 Delegation을 통해서 구조화를 하는 패턴이라고 생각이 듭니다.

제가 생각하는 내용을 아래의 형태별로 간단하게 코드로 끄적여 봅니다.
아래의 top-down은 layer별 interface가 필요할 것 같고, 그 인터페이스를 layer에 해당하는 기능 클래스(Level0201, Level0202)가 구현을 해서 상위 Layer가 하위 Layer에 Dependency를 줄이면서 사용하면 될 것 같습니다.
그리고, bottom-up은 상속을 통해서 상위 클래스의 메쏘드를 호출하는 형태로 구현을 해 봤습니다. 

혹시 코드보시고, 틀렸다고 생각이 되시는 부분이 있으면 답글로 끄적여 주시면 감사하겠습니다.

1. Top-Down Layer 형태

Level01.java
package layer.down;

import java.nio.ByteBuffer;

public class Level01 {
    ByteBuffer buffer;
    Level02Interface levelTwo; // Level02-1
   
    public void setByteBuffer(ByteBuffer buffer) {
        this.buffer = buffer;
    }
   
    public void setLevel() {
        this.levelTwo = new Level0201();
    }
   

    public void printLevel() {
        if(buffer.getInt() == 4)
            this.levelTwo = new Level0202();
       
        System.out.println("Level01 printLevel() called");
        this.levelTwo.foo();       
    }
}

Level02Interface.java
package layer.down;

public interface Level02Interface {

    public void foo();
}

Level0201.java
package layer.down;

public class Level0201 implements Level02Interface {

    @Override
    public void foo() {
        // TODO Auto-generated method stub
        System.out.println("Level0201 printLevel() called");
    }
}

Level0202.java

package layer.down;

public class Level0202 implements Level02Interface {

    @Override
    public void foo() {
        // TODO Auto-generated method stub
        System.out.println("Level0202 printLevel() called");
    }
}

클라이언트
        ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.putInt(4);
        buffer.flip();
       
        Level01 layer = new Level01();
        layer.setByteBuffer(buffer);
        layer.setLevel();
        layer.printLevel();   


2. Bottom-Up Layer 형태

SLevel01.java
package layer.up;

public class SLevel01 {
   
    //
    public void read(java.nio.ByteBuffer buffer) {
        System.out.println("level01 - "+ buffer.getInt());
    }
}


SLevel02.java
package layer.up;

public class SLevel02 extends SLevel01 {

    @Override
    public void read(java.nio.ByteBuffer buffer) {
        System.out.println("level02 - " + buffer.getInt());
       
        super.read(buffer);
    }
}


클라이언트
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.putInt(4);
        buffer.putInt(100);
        buffer.flip();
       
        SLevel02 layer = new SLevel02();
        layer.read(buffer);   

저작자 표시

'Ooad' 카테고리의 다른 글

POSA 1 - Whole-Part Pattern  (0) 2009/06/16
POSA 1 - Presentation Abstraction Control Pattern  (0) 2009/06/15
POSA 1 - Layers Pattern  (0) 2009/06/09
POSA 2 - A System of Patterns  (0) 2008/07/28
Design Pattern Quick Reference Image  (0) 2008/07/03

POSA 2 - A System of Patterns

from Ooad 2008/07/28 15:08
디자인 패턴에서 POSA(PATTERN-ORIENTED SOFTWARE ARCHITECTURE) 패턴은 중/고급에 속하는 패턴이라고 일반적으로 인식이 되어 있습니다.
그 중에서 POSA Volume 1은 A System of Patterns 라는 부제로, 디자인 패턴보다는 하이레벨에서 좀더 큰 시스템 개발에서의 패턴을 바라보고 있는거 같습니다.
아래 내용은 http://www.gisdeveloper.co.kr/389 에서 발췌를 하였습니다.

Layer A.P. 어플케이션을 구조화하기 위해 서브 태스크(Subtask)들을 그룹으로 묶기 위해 분해한다. 공통된 추상 레벨에 있는 서브 태스크들끼리 묶어서 그룹으로 분류한다.

Pipes and Filters A.P. 데이터 스트림을 처리하는 시스템 구조를 제공한다. 각 프로세싱 단계는 필터 컴포넌트로 추상화한다. 데이터는 파이프를 통해 연관된 필터들에게 전달된다. 필터들을 다양하게 재조합하여 시스템을 재구축할 수 있다.

Blackboard A.P. 정의되지 않은 도메인에서의 문제를 해결할때 유용하다. 솔루션에 대한 부분적이거나 대략적인 해법을 수립하기 위해 몇가지 특수한 서브시스템들의 지식을 조합한다.

Broker A.P. 분산 소프트웨어 시스템을 구조화할때 유용하다. 분산 소프트웨어 시스템은 분리된 컴포넌트들이 서로 유기적으로 조합되어 운영되는 시스템으로, 이러한 컴포넌트들 간의 통신을 관장하는 역활을 하는 것이 Broker이다.

Model-View-Controller A.P. 모델은 핵심기능과 데이터를 의미하고 뷰는 기능에 의한 데이터의 표현이며 컨트롤은 사용자의 입력에 대한 처리이다. 뷰와 컨트롤러는 사용자의 인터페이스를 구성하며 사용자 인터페이스와 모델간의 일관성 및 정합성을 보장한다.

Presentation-Abstraction-Control A.P. 계층구조를 이루는 에이전트들이 상호작용하는 소프트웨어 시스템에 대한 패턴. 각각의 에이전트는 하나의 어플리케이션의 특정 부분을 전담하며 에이전트는 프리젠테이션/추상/컨트롤로 구성된다.

Microkernel A.P. 변화하는 시스템에 대한 요구사항을 수용할 수 있도록 하는 패턴. 시스템에서 가장 최하단에 위치하는 핵심 기능을 추출해 내며, 추가된 요구사항에 대해 확장기능으로 정의하여 시스템에 손쉽게 추가할 수 있도록 한다.

Reflection A.P. 소프트웨어 시스템의 구조와 동작을 동적으로 변경할 수 있는 메커니즘을 제공.

Whole-Part D.P. 전체(Whole) 객체를 구성하는 컴포넌트(Part)를 정의한다. Whole 객체를 통해 Part 컴포넌트들의 관계를 맺으며, 이 Whole 객체를 통해서만 Part 컴포넌트와 통신할 수 있다.

Master-Slave D.P. 마스터 컴포넌트는 슬레이브 컴포넌트에게 작업을 분산시켜서 최종적으로 슬레이브로부터 그 결과를 취합한다.

Proxy D.P. 실제 컴포넌트가 아닌 대리자를 앞단에 두어 이 대리자를 통해 실제 컴포넌트와 통신을 한다. 실제 컴포넌트의 위치 추상화, 실제 컴포넌트를 사용하기 위한 인증 등과 같은 전처리는 물론 후처리에 대한 기능 추가가 용이하다.

Command Processor D.P. 사용자의 요청을 하나의 객체로 정의하여 관리하며 Undo/Redo와 같은 처리가 가능하다.

View Handler D.P. 시스템의 모든 뷰를 관리하는 책임을 분리하여 뷰들 간의 관계성과 연관된 작업을 쉽게 처리할 수 있도록 한다.

Forwarder-Receiver D.P. 투명한 IPC를 제공하고 Peer를 분리하기 위해 Forwarder와 Receiver를 분리한다.

Client-Dispatcher-Server D.P. 클라이언트와 서버 사이에 디스패처 레이어를 도입한다. 위치 투명성을 제공하고 클라이언트와 서버간의 통신에 대한 세부적인 구현을 캡출화한다.

Publisher-Subscriber D.P. 서로 긴밀하게 관계를 맺고 있는 컴포넌트들 간의 상태에 대해 정합성을 유지하는데 용이하다. Publisher가 책임을 지고 하나의 변경에 대해 다수의 Subscriber에게 변경을 통지한다.

'Ooad' 카테고리의 다른 글

POSA 1 - Presentation Abstraction Control Pattern  (0) 2009/06/15
POSA 1 - Layers Pattern  (0) 2009/06/09
POSA 2 - A System of Patterns  (0) 2008/07/28
Design Pattern Quick Reference Image  (0) 2008/07/03
Reactor VS Proactor  (0) 2008/06/10
Design Pattern's Quick Reference Image
http://www.mcdonaldland.info/2007/11/28/40/ 에서 pdf를 다운로드 받아서 이미지로 캡처를 했습니다.

사용자 삽입 이미지
사용자 삽입 이미지

'Ooad' 카테고리의 다른 글

POSA 1 - Layers Pattern  (0) 2009/06/09
POSA 2 - A System of Patterns  (0) 2008/07/28
Design Pattern Quick Reference Image  (0) 2008/07/03
Reactor VS Proactor  (0) 2008/06/10
LSP(Liskov Substitution Principle) ..  (0) 2008/06/03

Reactor VS Proactor

from Ooad 2008/06/10 15:09
Reactor 패턴은 소켓이나 파일에서 이벤트가 발생하면, 동기(Sync) I/O를 수행할 수 있는 상태를 체크하고, 이벤트에 맞는 핸들러를 호출해서 이벤트를 처리하는 방식이다. 만약, 서버소켓으로 새로운 커넥션 요청이 들어왔다면, Reactor는 내부 쓰레드를 통해 새로 들어온 커넥션을 처리하는 핸들러(Acceptor)를 호출해 커넥션을 처리한다.

Proactor 프레임워크는 하나 이상의 비동기 I/O가 초기화됐거나 또는 수행이 완료되어서 발생되는 이벤트에 대해 핸들러를 등록받아 처리한다. Proactor의 비동기 I/O를 사용할 경우, 유저 쓰레드가 I/O 작업을 직접 수행하지 않기 때문에, 동시성 문제에 있어서 많은 이점을 누릴 수 있게 되어 성능 향상을 꾀할 수 있다.

'Ooad' 카테고리의 다른 글

POSA 2 - A System of Patterns  (0) 2008/07/28
Design Pattern Quick Reference Image  (0) 2008/07/03
Reactor VS Proactor  (0) 2008/06/10
LSP(Liskov Substitution Principle) ..  (0) 2008/06/03
Comparing Two High-Performance I/O Design Patterns  (0) 2008/05/27
Tag // Proactor, Reactor
1988년 Babara Liskov는 자신의 논문에서 "자식 클래스들은 부모 클래스의 인터페이스를 통해서 사용 가능해야 하고 사용자는 그 차이를 몰라야 한다" 라고 우김..
의미 - 상위 클래스가 사용되는 곳에는 하위 클래스가 사용될 수 있어야 한다.

아래는 에레에 대해서 로깅을 하는 예제코드 입니다.
아래코드는 간단하게 C#으로 되었습니다. ^^
public class ExceptionLogger  
{  
    public void Log(Exception ex)  
    {  
        Console.WriteLine("An exception has occurred.");  
        Console.WriteLine(ex.ToString());  
    }  

-------------------------------------------------------------------------------------------------------------------------
public class FileExceptionLogger  
{  
    public void Log(Exception ex, string fileName)  
    {  
        using (StreamWriter sw = new StreamWriter(fileName))  
        {  
            sw.WriteLine(ex.ToString());  
        }  
    }  
}  
 
public class EmailExceptionLogger  
{  
    public void Log(Exception ex, string server, string toAddress)  
    {  
        MailMessage msg = new MailMessage("errors@testcompany.com", toAddress);  
        msg.Subject = "An exception has occurred.";  
        msg.Body = ex.ToString();  
        SmtpClient client = new SmtpClient(server);  
    client.Send(msg);  
    }  

-------------------------------------------------------------------------------------------------------------------------
// 위의 화면, 파일, 이메일 로그에 대해서 개별적인 기능 제공에 대한 문제
public static void Main(string[] args)  
{  
    ExceptionLogger log = new ExceptionLogger();  
    FileExceptionLogger fileLogger = new FileExceptionLogger();  
    EmailExceptionLogger emailLogger = new EmailExceptionLogger();  
 
    try 
    {  
        NestedException();  
    }  
    catch (Exception ex)  
    {  
        log.Log(ex);  
        fileLogger.Log(ex, "errors.log");  
        emailLogger.Log(ex, "localhost", "myemail@testcompany.com");  
    }  

-------------------------------------------------------------------------------------------------------------------------
// 위의 개별 클래스, 개별기능으로 인해서 로깅에 대한 모듈이 확장성이 없어지는 문제를 아래와 같이 해결할 수 있다는 내용입니다.

public interface ExceptionLogger  
{  
    public abstract void Log(Exception ex);  
}  
 
public class ConsoleExceptionLogger : ExceptionLogger  
{  
    public void Log(Exception ex)  
    {  
        Console.WriteLine("An exception has occurred.");  
        Console.WriteLine(ex.ToString());  
    }  
}  
 
public class FileExceptionLogger : ExceptionLogger  
{  
    public void Log(Exception ex)  
    {  
        // can't really do anything without a filename  
        // just want to fill out the interface.  
    }  
 
    public void Log(Exception ex, string fileName)  
    {  
        using (StreamWriter sw = new StreamWriter(fileName))  
        {  
            sw.WriteLine(ex.ToString());  
        }  
    }  
}  
 
public class EmailExceptionLogger : ExceptionLogger  
{  
    public void Log(Exception ex)  
    {  
        // see Log(Exception) on FileExceptionLogger  
    }  
 
    public void Log(Exception ex, string server, string toAddress)  
    {  
        MailMessage msg = new MailMessage("errors@testcompany.com", toAddress);  
        msg.Subject = "An exception has occurred.";  
        msg.Body = ex.ToString();  
        SmtpClient client = new SmtpClient(server);  
    client.Send(msg);  
    }  

-------------------------------------------------------------------------------------------------------------------------
// 위는 로깅에 대한 모듈이 확장성이 있지만 개별기능에 대해서 호출하는 문제를 아래와 같이 공통기능으로 뽑아서 공통 메쏘드를 호출할 수 있도록 해 주는 솔루션입니다.

public class FileExceptionLogger : ExceptionLogger  
{  
    private readonly string fileName;  
    public FileExceptionLogger(string file)  
    {  
        this.fileName = file;  
    }  
 
    public void Log(Exception ex)  
    {  
        using (StreamWriter sw = new StreamWriter(fileName))  
        {  
            sw.WriteLine(ex.ToString());  
        }  
    }  
}  
 
public class EmailExceptionLogger : ExceptionLogger  
{  
    private readonly string server;  
    private readonly string toAddress;  
    public EmailExceptionLogger(string smtpServer, string to)  
    {  
        this.server = smtpServer;  
        this.toAddress = to;  
    }  
 
    public void Log(Exception ex)  
    {  
        MailMessage msg = new MailMessage("errors@testcompany.com", toAddress);  
        msg.Subject = "An exception has occurred.";  
        msg.Body = ex.ToString();  
        SmtpClient client = new SmtpClient(server);  
    client.Send(msg);  
    }  







'Ooad' 카테고리의 다른 글

Design Pattern Quick Reference Image  (0) 2008/07/03
Reactor VS Proactor  (0) 2008/06/10
LSP(Liskov Substitution Principle) ..  (0) 2008/06/03
Comparing Two High-Performance I/O Design Patterns  (0) 2008/05/27
MVC(Model-View-Controller) 패턴  (0) 2008/04/21
Tag // java, lsp
Reactor 패턴과 Proactor 패턴에 대한 비교 자료입니다.
위의 패턴들은 더글라스 슈미츠 박사의 ACE 프레임웍에서 구현을 하였고, 패턴으로 승화가 되었죠.. ^^

아래 내용에서 TProactor 패턴에 대한 얘기가 나오고 있습니다.
소스를 까보면 Leader/Followers 패턴도 적용이 되어 있네요..
결국 기본적으로 IO에 대한 멀티플랙스 + 효율적인 처리를 위한 쓰레드 적용을 통해서 성능을 높이는 것이 TProactor 패턴으로 느껴집니다.

한번씩 읽어보세요.. ^^
 
http://www.artima.com/articles/io_design_patternsP.html

'Ooad' 카테고리의 다른 글

Reactor VS Proactor  (0) 2008/06/10
LSP(Liskov Substitution Principle) ..  (0) 2008/06/03
Comparing Two High-Performance I/O Design Patterns  (0) 2008/05/27
MVC(Model-View-Controller) 패턴  (0) 2008/04/21
Association Vs Aggregation Vs Composition  (0) 2008/03/17
Tag // POSA, Proactor, Reactor

MVC(Model-View-Controller) 패턴

from Ooad 2008/04/21 21:35
MVC 패턴에 대한 내용입니다.
아래 내용은 http://en.wikipedia.org/wiki/Model-view-controller 에서 정의한 내용입니다.

Model
The domain-specific representation of the information on which the application operates. Domain logic adds meaning to raw data (e.g., calculating if today is the user's birthday, or the totals, taxes, and shipping charges for shopping cart items).
Many applications use a persistent storage mechanism (such as a database ) to store data. MVC does not specifically mention the data access layer because it is understood to be underneath or encapsulated by the Model.
View
Renders the model into a form suitable for interaction, typically a user interface element. Multiple views can exist for a single model for different purposes.
Controller
Processes and responds to events, typically user actions, and may invoke changes on the model.

예제코드

Model.java

import java.util.*;

public class Model {
    private int x;
    private int y;
    private ArrayList<Model> arrList = new ArrayList<Model>();
   
    public Model(int i, int j) {
        this.x = i;
        this.y = j;
    }
   
    public void setModel(int x) {
        for(int i=0; i < x; i++) {   
            arrList.add(new Model(i, i+1));
        }
    }
   
    public ArrayList<Model> getArrayList() {
        return this.arrList;
    }
   
    public int getX(){
        return this.x;
    }
   
    public int getY(){
        return this.y;
    }
}

View.java

import java.util.*;

public class View {
    private static Controller con = null;
   
    // x, y 축 보기
    public static void viewList() {       
        ArrayList<Model> arrayList = View.con.getModelList();
        for(int i = 0; i < arrayList.size(); i++ ) {
            System.out.println(arrayList.get(i).getX() + ", " + arrayList.get(i).getY());
        }
    }
   
    // x축 보기
    public static void viewLine(){
        ArrayList<Model> arrayList = View.con.getModelList(20);
       
        for(int i = 0; i < arrayList.size(); i++ ) {
            System.out.println(arrayList.get(i).getX());
        }
    }
   
    public static void main(String[] args) {
        // TODO Auto-generated method stub
       
        con = new Controller();
        viewList();
        viewLine();   
    }
}

Controller.java

import java.util.*;

public class Controller {
    private Model model= null;
   
    public Controller() {
        this.model = new Model(1,1);
    }
   
    public ArrayList<Model> getModelList() {
        model.setModel(10);
        return model.getArrayList();
    }
   
    public ArrayList<Model> getModelList(int count) {
        model.setModel(count);
        return model.getArrayList();
    }   
}

'Ooad' 카테고리의 다른 글

LSP(Liskov Substitution Principle) ..  (0) 2008/06/03
Comparing Two High-Performance I/O Design Patterns  (0) 2008/05/27
MVC(Model-View-Controller) 패턴  (0) 2008/04/21
Association Vs Aggregation Vs Composition  (0) 2008/03/17
OOAD 란??  (0) 2008/02/19
An Association is a channel between classes through which messages can be sent. As sending messages translates to calling methods in Java, Associations are typically (but not necessarily) implemented by references.

An Aggregation is an Association which denotes an "is part of" relationship. Unfortunately, the definition of this relationship is quite lax, so basically everyone is using his own interpretation. The only definitive (?) property is that in an instance graph, aggregations are not allowed to be circular - that is, an object can not be "a part of itself". (or) When building new classes from existing classes using aggregation, a composite object built from other constituent objects that are its parts.Java supports aggregation of objects by reference,since objects can't contain other objects explicitly.

A Composition adds a lifetime responsibility to Aggregation. In a garbage collected language like Java it basically means that the whole has the responsibility of preventing the garbage collector to prematurely collect the part - for example by holding a reference to it. (In a language like C++, where you need to explicitely destroy objects, Composition is a much more important concept.) Only one whole at a time can have a composition relationship to a part, but that relationship doesn't need to last for the whole lifetime of the objects - with other words, lifetime responsibility can be handed around.

Aggregation and Composition Guidelines :

Sometimes an object is made up of other objects. For example, an airplane is made up of a fuselage, wings, engines, landing gear, flaps, and so on. A delivery shipment contains one or more packages. A team consists of two or more employees. These are all examples of the concept of aggregation, which represents 밿s part of?relationships. An engine is part of a plane, a package is part of a shipment, and an employee is part of a team. Aggregation is a specialization of association, specifying a whole-part relationship between two objects. Composition is a stronger form of aggregation where the whole and parts have coincident lifetimes, and it is very common for the whole to manage the lifecycle of its parts. From a stylistic point of view, because aggregation and composition are both specializations of association the guidelines for associations apply.

출처는 http://faq.javaranch.com/java/AssociationVsAggregationVsComposition 입니다.

'Ooad' 카테고리의 다른 글

LSP(Liskov Substitution Principle) ..  (0) 2008/06/03
Comparing Two High-Performance I/O Design Patterns  (0) 2008/05/27
MVC(Model-View-Controller) 패턴  (0) 2008/04/21
Association Vs Aggregation Vs Composition  (0) 2008/03/17
OOAD 란??  (0) 2008/02/19

OOAD 란??

from Ooad 2008/02/19 22:01

Object-Oriented Analysis and Design (OOAD) is a software engineering approach that models a system as a group of interacting objects.

Object-Oriented analysis (OOA) applies object-modeling techniques to analyze the functional requirements for a system.

Object-Oriented design (OOD) elaborates the analysis models to produce implementation specifications. OOA focuses on what the system does, OOD on how the system does it.

'Ooad' 카테고리의 다른 글

LSP(Liskov Substitution Principle) ..  (0) 2008/06/03
Comparing Two High-Performance I/O Design Patterns  (0) 2008/05/27
MVC(Model-View-Controller) 패턴  (0) 2008/04/21
Association Vs Aggregation Vs Composition  (0) 2008/03/17
OOAD 란??  (0) 2008/02/19
Tag // ooa, ooad, OOD