sjava-config 1.0

from My Project 2009/06/30 10:37
설정파일을 저장하고 가져오는 라이브러리입니다.
sjava-config는 http://www.jconfig.org/jconfig를 보고 필요한 형태(xml만 지원)로만 개발했습니다.
여러형태의 설정파일을 읽어올 수 있도록 common한 기능은 추상 클래스로 빼고 설정을 읽는 코드는 하위 클래스에서 구현을 합니다.

설정파일의 형태는 아래와 같습니다.
sjava-config.xml
<?xml version="1.0" encoding="utf-8"?>
<sjava-config>
    <!-- array variable delimeter is "," -->
    <!-- sjava-config 설정, 아래 설정은 지우지 마세요 -->
    <sjava-service name="config">
        <key name="watch" value="true" /> <!-- true, false -->
        <key name="interval" value="60" /> <!-- 60 seconds -->
    </sjava-service>
   
    <!-- 로그서버 설정 -->
    <sjava-service name="log">
        <key name="host" value="111.111.111.111,222.222.222.222" />
        <key name="port" value="20003" />
    </sjava-service>
</sjava-config>

그리고 위 파일(sjava-config.xml)은 classpath에 위치를 해야 읽을 수 있습니다.

ConfigTest.java
package net.sjava.config.demo;

import net.sjava.config.ConfigHandler;

/**
 * Code Coverage Test Class using EclEmma
 * @author mcsong@gmail.com
 * @since 2009. 6. 29.
 */
public class ConfigTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
       
        ConfigHandler configHandler = ConfigHandler.getInstance();
        System.out.println(configHandler.isLoading() ? "loading true" : "loading fail");
       
        System.out.println("- get vlaue test ---");
        System.out.println(configHandler.getValue("config", "watch"));
        System.out.println(configHandler.getValue("config", "interval"));
        System.out.println(configHandler.getValue("log", "host"));
        System.out.println(configHandler.getValue("log", "port"));
        System.out.println(configHandler.getValue("auth", "host"));
        System.out.println(configHandler.getValue("auth", "port"));
       
        System.out.println("- default value test ---");
        System.out.println(configHandler.getValue("config", "watch", "false"));
        System.out.println(configHandler.getValue("config", "interval", "11"));
        System.out.println(configHandler.getValue("log", "host", "222.222.222.222"));
        System.out.println(configHandler.getValue("log", "port", "20003"));
        System.out.println(configHandler.getValue("auth", "host", "222.222.222.222"));
       
        System.out.println("- array value test ---");
        for(int i = 0; i < configHandler.getValues("log", "host").length; i++) {
            System.out.println(configHandler.getValues("log", "host")[i].toString());
        }
       
        for(int i = 0; i < configHandler.getValues("auth", "host").length; i++) {
            System.out.println(configHandler.getValues("auth", "host")[i].toString());
        }
       
        System.out.println("- add value ---");
        configHandler.addValue("test", "host", "1.1.1.1");
        System.out.println(configHandler.getValue("test", "host"));
       
        System.out.println("- modify value ---");
        configHandler.setValue("test", "host", "2.2.2.2");
        System.out.println(configHandler.getValue("test", "host"));
       
        System.out.println("- modify values ---");
        String[] values = {"2.2.2.2", "3.3.3.3"};
        configHandler.setValues("test", "host", values);
       
        for(int i = 0; i < configHandler.getValues("test", "host").length; i++) {
            System.out.println(configHandler.getValues("test", "host")[i].toString());
        }
    }

}

바이너리

소스

'My Project' 카테고리의 다른 글

sjava-logging 1.0 Level  (0) 2009/07/13
sjava-logging 1.0  (0) 2009/07/09
sjava-config 1.2  (0) 2009/07/08
sjava-config 1.1  (0) 2009/07/03
sjava-config 1.0  (0) 2009/06/30

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
문자열을 비교하는 코드는 프로그램을 개발하다보면 많이 사용하게 됩니다.
보통 아래처럼 많이 비교하게 됩니다. 하지만, 잠재적으로 문제상황을 내재를 하고 있죵..

public void compareType(Stirng type)
{
    if(type.equals("AAA"))
        ...
    else if(type.equals("BBB"))
        ...
    else if(type.equals("CCC"))
        ...
}

위의 코드를 아래처럼 바꾸게 되면, 잠재적인 NullPointerException 상황을 피할수 있네요.

public void compareType(Stirng type)
{
    if("AAA".equals(type))
        ...
    else if("BBB".equals(type))
        ...
    else if("CCC".equals(type))
        ...
}

위 내용은 http://entireboy.egloos.com/2411775 에서 참고를 하였습니다.
Tag // equals, java
흠.. 로그 처리를 위한 파일에 스트링을 추가하는 클래스를 BufferedWriter로 구현을 하다가 갑자기 BufferedOutputStream으로 하는것과의 차이점을 알고 싶어서 아래의 코드로 차이를 살펴봤습니다.
아래의 BufferWriterTest, BufferOutputStream 클래스의 buffersize는 1024로 동일합니다.

BufferWriterTest.java
import java.util.*;
import java.text.*;
import java.io.*;

public class BufferWriterTest {
    //
    static DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
   
    static String txt = "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하" +
            "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라" +
            "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하" +
            "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하" +
            "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하" +
            "가나다라마바사아자차타파하가나다라마바사아자차타파하" +
            "가나다라마바사아자차타파하가나다라마바사아자차타파하" +
            "가나다라마바사아자차타파하마바사아자차타파하";
   
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Date start = new Date();   
        System.out.println("s - " + df.format(start));
       
        BufferedWriter bufferWriter;
       
        try {
           
            bufferWriter = new BufferedWriter(new FileWriter("c:\\BufferedWriter.txt", true), 1024);
           
            for(int i=0; i < 5000000; i++) {
                bufferWriter.write(BufferWriterTest.txt);
                bufferWriter.newLine();
            }
           
            bufferWriter.flush();
            bufferWriter.close();
           
        } catch (IOException e) {
            e.printStackTrace();
        }
       
        Date end = new Date();   
        System.out.println("e - " + df.format(end));
    }
}

실행화면(3.15G 파일 쓰기)

s - 2009-06-19 15:55:00:968
e - 2009-06-19 15:55:48:280

BufferOutputStream.java
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;

public class BufferOutputStream {
    //
    static DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
   
    static String txt = "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하" +
            "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라" +
            "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하" +
            "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하" +
            "가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하가나다라마바사아자차타파하" +
            "가나다라마바사아자차타파하가나다라마바사아자차타파하" +
            "가나다라마바사아자차타파하가나다라마바사아자차타파하" +
            "가나다라마바사아자차타파하마바사아자차타파하";
   
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Date start = new Date();   
        System.out.println("s - " + df.format(start));
               
        BufferedOutputStream bufferedOutput;
  
        try {
            bufferedOutput = new BufferedOutputStream(new FileOutputStream("c:\\BufferedStream.txt", true), 1024);
           
            for(int i=0; i < 5000000; i++) {
                bufferedOutput.write(txt.getBytes());
                bufferedOutput.write("\n".getBytes());
            }
           
            bufferedOutput.close();
           
        } catch (IOException e) {
            e.printStackTrace();
        }
       
        Date end = new Date();   
        System.out.println("e - " + df.format(end));
    }

}

실행화면(3.10G 파일 쓰기)

s - 2009-06-19 15:56:41:889
e - 2009-06-19 15:58:19:825

위 결과로 보면, 비슷한 사이즈의 파일을 추가할 경우에 실행속도가 꽤 차이가 나네요.. ^^;;
그냥 느낌에는 비슷한 실행시간이 될 것으로 생각이 들었는데요..
아래의 구조때문에 그럴까요?? 혹시 아시는 분은 조언을.. 

BufferedWriter BufferedOutputStream
java.lang.Object
  - java.io.Writer
    - java.io.BufferedWriter
java.lang.Object
 - java.io.OutputStream
   - java.io.FilterOutputStream
     - java.io.BufferedOutputStream






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
eclipse에서 ant로 빌드시에 javadoc를 이용해서 document를 해 주고 있는데, ant cannot run program javadoc.exe 에러가 발생을 하네요.. ^^;;;

그래서 확인해 봤더니..
java.home이 잘못 세팅이 되어 있습니다. ^^;;
<echo>${java.home}</echo>
C:\Program Files\Java\jre6

eclipse에서 아래처럼 ant의 설정에 java.home을 추가해서 위치를 조정해 주면 쉽게 해결이 됩니다. ^^


'Tools' 카테고리의 다른 글

Apache JMeter 사용하기  (0) 2010/01/13
Another java decompiler  (0) 2010/01/13
eclipse에서 ant로 javadoc task 에러  (0) 2009/06/11
무료 플래시 차트 'Open Flash Chart'..  (0) 2008/09/04
eclipse에서 cvs 연결끊기..  (0) 2008/08/27

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