Design Pattern

Java - 생성 패턴 구현

Cold Bean 2024. 11. 10. 23:36
728x90

Singleton Pattern

  • 클래스의 인스턴스가 한 개만 생성되도록 보장하는 디자인 패턴
  • 하나의 인스턴스만 유지하기 때문에 리소스를 절약하고 전역적으로 상태를 공유할 수 있다.
  • 전역적으로 사용되기 때문에 예측하지 못한 동작을 일으키는 문제가 발생할 수 있고 테스트가 어렵다.

구현 예시

public class Singleton {
	private static Singleton instance;
    private String data = "";
    
    private Singleton() {
		// private constructor
    }
    
    public static synchronized Singleton getInstance() {
    	if (instance == null) {
        	instance = new Singleton();
        }
        return instance;
    }
    
    public void data(String data) {
    	data = data;
    }
}

 

Factory Pattern

  • 팩토리 클래스를 통해 객체 생성 로직을 캡슐화하는 디자인 패턴
  • 클라이언트 코드가 직접 인스턴스 객체를 생성하지 않기 때문에, 시스템 전체 코드의 결합도를 줄이고 확장성을 높일 수 있다. 
  • 다양한 타입의 객체를 생성할 때 유용 (ex) GUI 툴킷, 데이터베이스 연결, 파일 포맷 변환)

구현 예시

public interface Animal {
	void speak();
}
public class Dog implements Animal {
	@Override
    public void speak() {
		System.out.println("MungMung!");
	}
}
public class Cat implements Animal {
	@Override
    public void speak() {
		System.out.println("Meow");
	}
}
public class AnimalFactory {
	public Animal createAnimal(String type) {
    	if(type.equalsIgnoreCase("dog")) {
        	return new Dog();
        } else if (type.equalsIgnoreCase("cat")) {
        	return new Cat();
        }
        return null;
    }
}

클라이언트 코드는 이제 AnimalFactory를 사용하여 원하는 Animal 객체를 생성할 수 있다.

즉, 클라이언트 코드는 Dog나 Cat 객체 세부 사항을 알 필요 없이 AnimalFactory를 통해 Animal 객체를 생성하고 사용할 수 있다.

이처럼 팩토리 클래스를 적용하여 클라이언트 코드와 구체 클래스의 결합도를 줄일 수 있다.

 

사용 예시

public class Client {
	public class void main(String[] args) {
    	AnimalFactory factory = new AnimalFactory();
        
        Animal dog = factory.createAnimal("dog");
        dog.speak();	// "MungMung!"
        
        Animal cat = factory.createAnimal("cat");
        cat.speak();	// "Meow"
    }
}

 

Builder Pattern

  • 빌더 패턴은 객체 생성 과정을 단계별로 분리한 디자인 패턴
  • 특히 선택적 매개변수를 가지고 있는 개겣를 생성할 때 유용
    • ex)  사용자 계정 생성, SQL 쿼리 작성, 제품의 특성 선택 등
  • 각 단계별 과정을 가독성 있게 구현할 수 있으며, 유지 보수 시에도 보다 용이하게 코드를 수정할 수 있다.

구현 예시

public class Pizza {
	private String dough;
    private String topping;
    
    private Pizza(PizzaBuilder builder) {
    	this.setDough(builder.dough);
        this.setTopping(builder.topping);
    }
    
    private void setDough(String dough) {
    	this.dough = dough;
    }
    
    private void setTopping(String topping) {
    	this.topping = topping;
    }
    
    private String getDough(String dough) {
    	return this.dough;
    }
    
    private String getTopping(String topping) {
    	return this.topping;
    }
    
    public static class PizzaBuilder {
    	private String dough;
        private String topping;
        
        public PizzaBuilder dough(String dough) {
        	this.dough = dough;
            return this;
        }
        
        public PizzaBuilder topping(String topping) {
        	this.topping = topping;
            return this;
        }
        
        public Pizza build() {
        	return new Pizza(this);
        }
    }
}

 

사용 예시

public class Client {
	public static void main(String[] args) {
    	Pizza pizza = new Pizza.PizzaBuilder()
        		.dough("cross")
                .topping("pepperoni")
                .build();
                
        System.out.println(pizza.getDough() + " / "
        		+ pizza.getTopping());
    }
}



728x90