4차산업혁명의 일꾼/Java&Spring웹개발과 서버 컴퓨터

디자인 패턴 1- 클래스의 인스턴스를 생성 -(Singleton Pattern,Prototype Pattern,abstract Factory Pattern,Builder Pattern : 싱글톤, 프로토타입, 공장, 빌더)

르무엘 2023. 2. 19. 23:09

박은종의 객체지향 설계를 위한 디자인패턴 with 자바

 

1. Singleton Pattern(클래스의 인스턴스는 오직 하나임을 보장하며 이 인스턴스에 접근할 수 있는 방법을 제공하는 패턴)

2. Prototype Pattern (복제해서 인스턴스를 만드는 패턴)

3. Abstract Factory Pattern (여러 제품군을 한꺼번에 생성하는 패턴)

4. Builder Pattern ( GoF 디자인 패턴에서의 Builder Pattern 이란? (메서드의 조합으로 결과물을 생성하는 방법) )

 

 

 

1. Singleton Pattern(클래스의 인스턴스는 오직 하나임을 보장하며 이 인스턴스에 접근할 수 있는 방법을 제공하는 패턴)

인스턴스 만들고 공용으로 사용

public class ConnectionPool {
	
	private static ConnectionPool instance = new ConnectionPool();
	
	private ConnectionPool() {}
	
	public static ConnectionPool getInstance() {
		
		if(instance == null) {
			instance = new ConnectionPool();
		}

		return instance; 
			
	}

}

 

 

2. Prototype Pattern (복제해서 인스턴스를 만드는 패턴)

 

  • 프로토타입 속성값을 활용하여 다양한 객체를 생성할 수 있음
  • 서브클래스의 수를 줄일 수 있다.
  • 자바에서는 clone() 메서드를 재정의하여 구현한다.
package prototype;

import java.util.ArrayList;

class Book{
	private String author;
	private String title;
	
	public Book(String author, String title) {
		this.author = author;
		this.title = title;
	}
	
	public String getAuthor() {
		return author;
	}
	
	public void setAuthor(String author) {
		this.author = author;
	}
	
	public String getTitle() {
		return title;
	}
	
	public void setTitle(String title) {
		this.title = title;
	}

	public String toString() {
		return title + "," + author;
	}
}


class BookShelf implements Cloneable{
	
	private ArrayList<Book> shelf;
	
	public BookShelf() {
		shelf = new ArrayList<Book>();
	} 
	
	public void addBook(Book book) {
		shelf.add(book);
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {

		BookShelf another = new BookShelf();
		for(Book book : shelf) {
			
			another.addBook(new Book(book.getAuthor(), book.getTitle()));
		}
		
		return another;
	}
	
	public ArrayList<Book> getShelf() {
		return shelf;
	}

	public void setShelf(ArrayList<Book> shelf) {
		this.shelf = shelf;
	}

	public String toString() {
		return shelf.toString();
	}
	
	
}

public class PrototypeTest {

	public static void main(String[] args) throws CloneNotSupportedException {

		BookShelf bookShelf = new BookShelf();
		
		bookShelf.addBook(new Book("orange", "Tomas"));
		bookShelf.addBook(new Book("apple", "James"));
		bookShelf.addBook(new Book("grape", "Edward"));
		
		
		BookShelf another = (BookShelf)bookShelf.clone();
		
		System.out.println(bookShelf);
		System.out.println(another);
		
		bookShelf.getShelf().get(0).setAuthor("Mango");
		bookShelf.getShelf().get(0).setTitle("Jane");
		
		System.out.println(bookShelf);
		System.out.println(another);
	}

}

 

 

3. Abstract Factory Pattern (여러 제품군을 한꺼번에 생성하는 패턴)

 

  • 일반적으로 ConcreteFactory 클래스의 인스턴스는 실행 할 때 만들어진다.
  • 구체적 팩토리는 어떤 특정 구현을 갖는 제품 객체를 생성한다. 서로 다른 제품 객체를 생성하기 위해서 사용자는 서로 다른 ConcretetFactory 를 사용한다.
  • AbstractFactory 는 ConcreteFactory 서브클래스를 통해 필요한 제품 객체를 생성하는 책임을 위임한다.

-> mysql , oracle 의dbtype에 따라 user, product 세

 

 

4. Builder Pattern ( GoF 디자인 패턴에서의 Builder Pattern 이란? (메서드의 조합으로 결과물을 생성하는 방법) )

 

  • 생성에 대한 과정과 각 결과물을 표현하는 방법을 분리하여 동일한 생성 과정에 서로 다른 여러 결과물이 나올 수 있도록 함
  • 클라이언트 코드는 Builder가 제공하는 메서드를 기반으로 원하는 결과물을 얻을 수 있음
  • 단계별 생성에 중점을 두는 패턴
  • 새로운 결과물이 필요한 경우에도 동일한 과정으로 생성을 할 수 있음

 

 

public abstract class Pizza {
	
	public enum Topping { HAM, MUSHROOM, ONION, PEPPER, SAUSAGE};
	final Set<Topping> toppings;
	
	abstract static class Builder {
		EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class);
		
		public Builder addTopping(Topping topping) {
			toppings.add(Objects.requireNonNull(topping));
			return self();
		}
		public Builder sauceInside() { 
			return self();
		}
		
		abstract Pizza build();
		protected abstract Builder self();
	}
	
	Pizza(Builder builder){
		
		toppings = builder.toppings.clone();
	}

	public String toString() {
		return toppings.toString();
	}
}
public class NyPizza extends Pizza{

	public enum Size { SMALL, MEDIUM, LARGE};
	private final Size size;
	
	public static class Builder extends Pizza.Builder {
			private final Size size;
			
			public Builder(Size size) {
				this.size = Objects.requireNonNull(size);
			}
			
			public NyPizza build() {
				return new NyPizza(this);
			}
			
			protected Builder self() {return this;}
	}
	
	private NyPizza(Builder builder) {
		super(builder);
		size = builder.size;
	}
}
public class Calzone extends Pizza{

	private final boolean sauceInside;
	
	public static class Builder extends Pizza.Builder{
		
		private boolean sauceInside = false;
		
		public Builder sauceInside() {
			sauceInside = true;
			return this;
		}
		
		public Calzone build() {
			return new Calzone(this);
		}
		
		protected Builder self() {return this;}
		
	}
	
	private Calzone(Builder builder) {
		super(builder);
		sauceInside = builder.sauceInside;
	}
	
	public String toString() {
		return toppings.toString() + " sauceInside: " + sauceInside;
	}
}
public class PizzaTest {

	public static void main(String[] args) {

		Pizza nyPizza = new NyPizza.Builder(Size.SMALL).addTopping(Topping.SAUSAGE)
				.addTopping(Topping.ONION).build();

		
		Pizza calzone = new Calzone.Builder().addTopping(Topping.HAM).addTopping(Topping.PEPPER)
				.sauceInside().build();
		
		System.out.println(nyPizza);
		System.out.println(calzone);
	}

}
LIST