태그 보관물: Design Pattern

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

cfile26.uf.183E69224AB1F4DC9FC5DB.zip

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

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

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

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

MVC(Model-View-Controller) 패턴


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