월별 글 목록: 2009년 9월월

Null Object Pattern

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 <a href="mailto:mcsong@gmail.com">mcsong@gmail.com</a>
* @since 2009. 9. 17.
*/

public interface ILogger {
/**
*
* @param log
*/
public void log(String log);
}

package net.sjava.patterns.nullobject;
/**
*
* @author <a href="mailto:mcsong@gmail.com">mcsong@gmail.com</a>
* @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 <a href="mailto:mcsong@gmail.com">mcsong@gmail.com</a>
* @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) {
    System.out.println("null log - " + log);
  }
}

</div>


<pre class="brush: java; gutter: true; auto-links: false">
package net.sjava.patterns.nullobject;
/**
*
* @author <a href="mailto:mcsong@gmail.com">mcsong@gmail.com</a>
* @since 2009. 9. 17.
*/
public class SocketLogger implements ILogger {

  @Override
  public void log(String log) {
    System.out.println("socket log - " + log);
  }
}
package net.sjava.patterns.nullobject;
/**
*
* @author <a href="mailto:mcsong@gmail.com">mcsong@gmail.com</a>
* @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) {
    handler = new LoggerHandler(null);
    handler.log("fileloggger");
    handler = new LoggerHandler(new FileLogger());
    handler.log("socketloggger");
    handler = new LoggerHandler(new SocketLogger());
    handler.log("socketloggger");
  }
}

160BCA214AB1F47908EC13.zip

Specification Pattern

이 패턴에 대해서, 위키피디아는 “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

아래는 예제 코드이다.

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());
		
	}
}

cfile26.uf.183E69224AB1F4DC9FC5DB.zip

디자인 패턴 그리고 그 이후..

몇일전에 에릭감마의 내한 세미나에 참석을 하였습니다.
거기서, 에릭감마는 디자인 패턴이 지금은 구식이 되어 버린 경우가 생겼고, 그것에 대한 계속적인 스터디가 필요하다고 말했던 것으로 기억을 하고 있습니다(아님 말고.. ^^;;).

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

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

한글 문자 확인하기..

캐릭터가 한글인지, 문자열에 한글이 포함되어 있는지를 체크할 수 있는 내용입니다.
reference는 http://blog.daum.net/kjourney/6386029 입니다.



public class KoreanCharacterExistTest {


 /**
  * 한글 문자를 체크한다.
  *
  * @param ch
  * @return
  */
 public static boolean isKoreanCharacter(char ch) {
  String block = Character.UnicodeBlock.of(ch).toString();
  
  if(block.equals(“HANGUL_JAMO”) || block.equals(“HANGUL_SYLLABLES”) || block.equals(“HANGUL_COMPATIBILITY_JAMO”))
   return true;
  
  return false;
 }
 
 /**
  * 한글 문자 포함여부를 체크한다.
  * @param str
  * @return
  */
 public static boolean isKoreanCharacterContained(String str){
  if(str == null || str.length() < 1)
   return false;
   
  for(int i=0; i< str.length(); i++){
   if(isKoreanCharacter(str.charAt(i)))
    return true;   
     }
  
  return false;
 }
 
 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  System.out.println(“sldkflkl – ” + isKoreanCharacterContained(“sldkflkl”));
     System.out.println(“가나다라 – ” + isKoreanCharacterContained(“가나다라”));
     System.out.println(“sldk가나 – ” + isKoreanCharacterContained(“sldk가나”));
     System.out.println(“가나kflkl – ” +isKoreanCharacterContained(“가나kflkl”));
 }
}