반응형
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 / share
package 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();
}
}
}
반응형
'Design Pattern' 카테고리의 다른 글
[Design pattern] 행위 패턴 (0) | 2019.06.14 |
---|---|
[Design pattern] 구조 패턴 (0) | 2019.06.13 |
[Design Pattern] Singleton 패턴 / Factory 패턴 (0) | 2019.06.13 |
댓글