-
[Design Pattern] Builder 패턴/Prototype 패턴/Object pool 패턴Computer Science/Design Pattern 2019. 6. 13. 14:04반응형
Builder pattern
생성 인자가 많은 경우
객체 생성 로직을 클래스 밖으로 옮길 필요
서로 연관된 복잡한 생성자를 가지고 있을 때
생성자의 복잡성
비즈니스 룰의 복잡성
한번에 모든 생성 데이터가 없을 때
단계적 생성package creation.builder; public class NutritionFacts { // TODO private final int servingSize; private final int servings; private final int calories; private final int fat; private final int sodium; public static class Builder { private final int servingSize; private final int servings; private int calories; private int fat; private int sodium; public Builder(int servingSize, int servings) { this.servingSize = servingSize; this.servings = servings; } // new Builder() -> Builder // (Builder).calories -> Builder // (Builder).fat public Builder calories(int val) { this.calories = val; return this; } public Builder fat(int val) { this.fat = val; return this; } // new Builder(1, 2).soldim(1).fat(2) public Builder sodium(int val) { this.sodium = val; return this; } // new Builder(1, 2).soldim(1).fat(2).build() -> NutritionFacts public NutritionFacts build() { return new NutritionFacts(this); } } private NutritionFacts(Builder builder) { servingSize = builder.servingSize; servings = builder.servings; calories = builder.calories; fat = builder.fat; sodium = builder.sodium; System.out.println("객체 생성"); } }
package creation.builder; public class Client { public static void main(String[] args) { // TODO NutritionFacts.Builder builder = new NutritionFacts.Builder(240, 8); builder.calories(100); builder.sodium(35); NutritionFacts n1 = builder.build(); NutritionFacts n2 = new NutritionFacts .Builder(240, 8) .calories(100) .build(); } }
Prototype pattern
런타임에 그 타입이 결정되는 거의 동일한 객체의 집합을 만들려고 할 때 적용
새로운 인스턴스가 필요할 때 이미 생성된 인스턴스를 클론화하여 사용
- DB에서 데이터를 가져와서 객체 생성하는 경우, 동일 데이터를 다시 DB에서 가져오기보다 이미 DB에서 데이터를 가져와서 생성된 객체를 복사해서 사용하면 효율적임
인스턴스를 만드는 방법
- New Something();
- MyPart anotherMyPart = MyPartPrototype.clone();
Shallow clone vs Deep clone
Shallow clone (얕은 복사)
- 기본형 타입 멤버 변수는 값을 복사
- 사용자 정의 객체를 멤버변수로 가진 경우, 그 멤버변수는 clone시 참조 주소 값 복사
- 즉, 복제된 객체 내의 사용자 정의 객체 멤버변수 변경시 원본 객체내의 사용자 정의 객체 멤버변수도 변경됨
Deep copy (깊은 복사)
- 사용자 정의 객체의 멤버변수의 참조 주소값이 아닌 새로운 주소를 할당하여 값을 복제
package creation.prototype; import java.util.ArrayList; import java.util.List; public class Users implements Cloneable { // TODO private List userList; public Users(List list) { this.userList = list; } public void loadData() { userList = new ArrayList(); userList.add("yunyoung1819"); userList.add("leekang"); } public List getUserList() { return this.userList; } public Object clone() throws CloneNotSupportedException { // return super.clone(); List temp = new ArrayList(); for (Object s : this.userList) { temp.add((String) s); } return new Users(temp); } }
package creation.prototype; public class Client { public static void main(String[] args) throws CloneNotSupportedException { Users origin = new Users(null); origin.loadData(); Users cloneU = (Users) origin.clone(); if (origin.getUserList() == cloneU.getUserList()) System.out.println("shallow"); else System.out.println("deep"); if (origin == cloneU) System.out.println("동일한 객체"); else System.out.println("복제된 객체"); } }
Object pool pattern
성능에 초점을 둔 패턴
DB Connection 생성은 expensive 하므로 사전에 생성된 객체를 재활용
reuse / sharepackage creation.pool; import java.util.ArrayList; import java.util.List; public class ObjectPool<T> { // TODO private List<T> availablePool; private List<T> inUsePool; private int maxPoolSize = 10; public ObjectPool(Class<T> classObj) throws Exception { createPool(classObj, this.maxPoolSize); } public ObjectPool(Class<T> classObj, int maxPoolSize) throws Exception { this.maxPoolSize = maxPoolSize; createPool(classObj, maxPoolSize); } private void createPool(Class<T> classObj, int maxPoolSize) throws Exception { this.maxPoolSize = maxPoolSize; this.availablePool = new ArrayList<T>(); this.inUsePool = new ArrayList<T>(); for (int i = 0; i < maxPoolSize; i++) { this.availablePool.add(classObj.newInstance()); } } public T getObject() { if (this.availablePool.size() == 0) { throw new PoolSizeOutException("사용할 객체가 없음"); } T instance = this.availablePool.get(0); availablePool.remove(0); inUsePool.add(instance); return instance; } static class PoolSizeOutException extends RuntimeException { public PoolSizeOutException(String message) { super(message); } } public boolean invalidate(T obj) { for (T data:inUsePool) { if (data != null && data == obj) { return true; } } return false; } }
package creation.pool; import creation.pool.ObjectPool.PoolSizeOutException; public class Client { public static void main(String[] args) throws Exception { // TODO try { ObjectPool<StringBuffer> pool = new ObjectPool<StringBuffer>(StringBuffer.class, 2); StringBuffer o1 = pool.getObject(); StringBuffer o2 = new StringBuffer(0); System.out.println(pool.invalidate(o1)); System.out.println(pool.invalidate(o2)); StringBuffer o3 = pool.getObject(); StringBuffer o4 = pool.getObject(); } catch (PoolSizeOutException e) { e.printStackTrace(); } } }
반응형'Computer Science > Design Pattern' 카테고리의 다른 글
[Design pattern] 행위 패턴 (0) 2019.06.14 [Design pattern] 구조 패턴 (0) 2019.06.13 [Design Pattern] Singleton 패턴 / Factory 패턴 (0) 2019.06.13