태그 보관물: POSA

POSA 1 – 마스터-슬레이브(Master-Slave) 패턴

마스터-슬레이브(Master-Slave) 패턴은 마스터(Master)가 슬레이브(Slave)에게 작업을 분산하고, 슬레이브가 처리한 결과로 최종 결과를 계산하는 패턴이다. 즉, 마스터는 작업을 쪼개고, 슬레이브에게 쪼갠 작업을 분배하고, 결과를 계산하는 역할을 한다. 그리고 슬레이브는 마스터의 작업 요청을 처리하고, 결과를 리턴한다.

그래서 위 패턴의 형태로 간단한 코드를 작성해 보자. 예제는 1부터 10까지의 factorial을 10개의 작업(Job)으로 나누고, 나눠진 작업의 결과를 마스터가 더해서 마지막 결과를 보여주는 예제이다.

아래의 MSClient는 클라이언트와 마스터 역할을 담당한다. JobThread는 슬레이브 역할을 담당한다.

– 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 jobArray = new ArrayList();
        ExecutorService executor =  Executors.newFixedThreadPool(10);
           
        for (int i = 1; i <= 10; i++) {
            jobArray.add(new JobThread(i));
        }
       
        List<Future> 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 {
    //
    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;
    }
}

POSA 1 – Whole-Part Pattern

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

POSA 1 – Presentation Abstraction Control Pattern

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
 

POSA 1 – 레이어(Layers) 패턴

레이어(Layers) 패턴을 간단하게 말하면, 복잡한 시스템을 레이어로 나눠서 작업(Task)를 하위 레이어나 상위 레이어로 전달(Delegation)하도록 구조화하는 패턴이다.

이 패턴을 간단하게 코드로 만들어 보자. 탑-다운(Top-Down)은 개별 레이어 인터페이스가 필요할 것이고, 각 레이어의 개별 인터페이스는 구현 클래스(Level0201, Level0202)에서 구현해서 상위 레이어가 하위 레이어에 의존하는 것을 줄인다. 그리고, 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 레이어

– 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);   

Comparing Two High-Performance I/O Design Patterns

Reactor 패턴과 Proactor 패턴에 대한 비교 자료입니다.
위의 패턴들은 더글라스 슈미츠 박사의 ACE 프레임웍에서 구현을 하였고, 패턴으로 승화가 되었죠.. ^^

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

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