디자인 패턴에 대하여

seunghyun lee·2022년 7월 12일
0

Computer Science

목록 보기
2/19
post-thumbnail

1. 디자인 패턴이란


  • 디자인 패턴

디자인 패턴은 프로그램을 개발하는 과정에서 빈번하게 발생하는 디자인 문제를 정리해서 상황에 따라 간편하게 적용할 수 있게 정리한 것이다.
소프트웨어 개발은 요구사항 분석 -> 설계 -> 구현 -> 테스트를 반복하게 되는데
이때, 디자인 패턴은 설계에 해당한다.


2. 디자인 패턴의 3가지 분류


1. 생성 패턴(Creational Pattern)

객체 생성에 관련된 패턴

2. 구조 패턴(Structural Pattern)

클래스나 객체를 조합해 더 큰 구조를 만드는 패턴

3. 행위 패턴(Behavior Pattern)

클래스와 객체들이 상호작용하는 방법과 역할을 분담하는 방법을 다루는 패턴


3.디자인 패턴의 23가지 종류


생성 패턴(Creational Pattern)

1. Abstract Factory

한 객체의 상태 변화에 따라 다른 객체의 상태도 연동되도록 일대다 객체 의존 관계를 구성하는 패턴

2. Builder

복잡한 객체를 생성하는 클래스와 표현하는 클래스를 분리하여, 동일한 절차에서도 서로 다른 표현을 생성하는 방법이다.

3. Factory Method

객체를 생성할 때 필요한 인터페이스를 만든다. 어떤 클래스의 인스턴스를 만들지는 서브클래스에서 결정한다.
팩토리 메소드 패턴을 사용하면 클래스 인스턴스 만드는 일을 서브클래스에게 맡기게 된다. .

4. Prototype

객체를 생성하는데 비용이 많이 들고, 비슷한 객체가 이미 있는 경우에 사용한다.
객체를 새로운 객체에 복사하여 필요에 따라 수정한다.

5. Singletone

특정 클래스의 객체 인스턴스가 하나만 만들어지도록 해주는 패턴
소프트웨어를 만들다보면 어떠한 클래스의 객체가, 해당 프로세스에 단 하나만 존재해야되는 경우가 생긴다. 예를들어 사용자가 페이지를 다크모드로 설정한다면 다른 페이지로 이동하더라도 다크모드가 유지되어야 한다. 즉, 어떤 페이지에 있든, setting 객체는 반드시 동일 객체여야 한다.

  • 코드 구현(올바르지 않은 예)
class FirstPage {
	public void setAndPrintSettings() {
    	Settings settings = new Settings();
        settings.darkMode = true;
        System.out.println(settings.darkMode);	// true 출력
    }
}
class SecondPage {
	public void printSettings() {
    	Settings settings = new Settings();
        System.out.println(settings.darkMode); // false출력
	}
	
}

class Settings{
	boolean darkMode = false;
}

위에서 FirstPage의 settings객체와 SecondPage의 settings객체는 서로 다른 메모리를 주소에 할당되어 있다. 즉, 서로 다른 객체이다. 따라서 FirstPage에서 darkMode로 변경해주어도 SecondPage에서는 적용이 안 된다.

  • 위의 코드는 아래와 같이 수정해야 한다.
class FirstPage {
	public void setAndPrintSettings() {
    	private Settings settings = Settings.getSetting(); // 그때그때 객체를 생성하지 않음
        settings.darkMode = true;
        System.out.println(settings.darkMode);	// true 출력
    }
}
class SecondPage {
	public void printSettings() {
    	private Settings settings = Settings.getSetting(); // static메서드 가져옴
        System.out.println(settings.darkMode); // true 출력 settings객체는 단 하나만 만들어졌기 때문
	}
	
}

class Settings{
	static boolean darkMode = false;	//변수를 static으로 바꾸어줌
    private Settings(){};// 생성자를 private으로 감싸줌
    private static Settings settings = null;
    
    public static Settings getSetting() { //메서드또한 static임
    	if(settings == null) {
        	settings = new Settings(); // 객체는 단 한 번 만들어짐
        }
        return settings;
    }
    static boolean getDarkMode(){return darkMode;}	
	
}

static으로 설정된 객체는 메모리의 지정된 공간에 단 하나만 존재할 수 있다.
setting객체가 static으로 선언되었을 때,
즉, FirstPage에서 setting 객체의 darkmode를 true로 변경해주면
SecondPage에서도 그 setting 객체의 darkmode값을 가져와 true라고 읽을 수 있다는 것이다.

  • 주의!

싱글턴을 잘 못사용하다보면 멀티 쓰레딩환경에서 오류가 발생할 수 있다.


구조 패턴(Structural Pattern)


6. Adapter

Adapter: 형식이 다른 두 도구 사이에 연결되어 그 둘이 호환될 수 있도록 하는 도구
인터페이스가 서로 다른 객체들이 같은 형식 아래 작동할 수 있도록 하는 역할을 한다.

7. Bridge

구현부에서 추상층을 분리하여 각자 독립적으로 변형할 수 있게 하는 패턴이다.

8. Composite

객체를 트리구조로 구성하여 계층구조를 구현할 때 사용한다.

9. Decorator

객체에 추가 요소를 동적으로 더할 수 있고, 서브 클래스를 만들때 보다 더 유연하게 기능을 확장할 수 있다.

10. Facade

여러 클래스의 객체들을 복합적으로 사용하여야 수행할 수 있는 작업이 있을 때, 클래스에 하나하나 접근하여 일일이 객체를 만들고 이를 연결하는 것은 상당히 비효율적이다.
작업을 실행하는 사용자 측에서 이러한 복잡한 연결관계를 알 필요가 없도록 프랑스어로 외벽을 뜻하는 facade class 뒤에 숨기는 것이다.

11. FlyWeight

클래스의 객체 한 개만 가지고 여러 개의 가상 인스턴스를 갖고 싶을 때 사용하는 패턴이다.
인스턴스를 가능한대로 공유시켜 new연산자를 통한 메모리 낭비를 줄이는 방식이다.

12. Proxy

특정 객체로의 접근을 제어하고, 대변하는 객체를 제공한다.
유튜브의 썸네일에 마우스를 가져가면, 유튜브의 프리뷰를 확인 할 수 있다.
제목을 화면에 나타내는 건 가벼운 작업이지만, 프리뷰를 보여주기 위해서는 영상데이터를 받아와야 한다. 썸네일을 담당하는 객체는 제목과 프리뷰를 두 메소드(제목 보여주기, 프리뷰보여주기)를 통해 각각 보여주도록 하되, 썸네일이 처음 화면에 나타날 때는 일단 제목만 보여줄 수 있는 프록시로 생성되게 하고, 프리뷰로 보여주는 무거운 작업은 실제 클래스가 담당하도록 해서, 프록시 객체로 생성된 썸네일에 커서를 올리면, 실제 클래스가 호출되어 프리뷰를 보여주게 한다.


행위 패턴(Behavior Pattern)


13. Chain of Responsibility

요구를 처리할 수 없는 요청이 들어온다면 수신하는 객체가 다음 객체에게 책임을 넘김으로써 최종적으로 요청을 처리할 수 있는 객체에 의해 처리가 가능하도록 하는 패턴이다.

14. Command

Strategy 패턴은 같은 일을 하되,알고리즘이나 방식이 교체 되는 거라면,
Command 패턴은 그 할 일 자체가 다른 것이다.
command패턴은 매우 다양하게 작성된다.
Strategy 패턴처럼 모드 변경에 따라 명령을 교체하는 식으로 작성하기도 하고, 여러 명령들을 목록으로 실어 보내 차례로 실행시킬 수도 있다.

15. Interpreter

간단한 언어의 문법을 정의하고 해석하는 패턴이다.

16. Iterator

컬렉션의 구현 방법을 노출하지 않으면서 집합체 내의 모든 항목에 접근하는 방법 제공한다.

17. Mediator

객체들의 집합이 상호작용하는지를 함축해놓은 객체를 정의한다.

18. Memento

객체의 상태 정보를 저장하고 사용자의 필요에 의해 원하는 시점의 데이터를 복원할 수 있는 패턴이다.

19. Observer

한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고 자동으로 내용이 갱신되는 일대다 의존성을 정의한다.

20. state

특정 상태마다 다르게 할 일을 특정 상태마다 실행시 할 일과 함께 하나하나 모듈화해서 지정할 때 사용한다.
ex) 앱 화면의 다크모드 여부를 켰다 껐다 한다면 다크모드에서 라이트 모드가 되고, 라이트 모드에서는 다크모드로 상태가 전환된다.
Strategy 패턴이 지정된 특정 메소드가 모듈화된 모드에 따라 다르게 실행되도록 한다면,
State는 메서드가 실행될 때, 모드도 전환되도록 하는 것이다.

21. Strategy

  • 프로그램 실행 중 모드가 바뀔 때마다 전략이 수정되는 경우
    모듈마다의 동작 하나하나를 모듈로 따로 분리하여, 모드가 바뀔때마다 실행되는 모듈을 교체하는 방식으로 코드를 방식이다.
interface SearchStrategy{
	public void search();
}

class SearchStrategyAll implements SearchStrategy {
	public void search() {System.out.println("Search All");}
}
class SearchStrategyImage implements SearchStrategy {
	public void search() {System.out.println("Search image");}
}
class SearchStrategyMap implements SearchStrategy {
	public void search() {System.out.println("Search map");}
}
public class SearchButton{
	SearchStrategy searchStrategy = new SearchStrategyAll();
    public void setSearchStrategy(SearchStrategy _searchStrategy) {
    	SearchStrategy = _ searchStrategy;// <<모드에 따라 setSearchStrategy을 통해 모듈을 갈아끼운다
    }
}

위처럼 SearchStrategey라는 인터페이스와 그 인터페이스를 implements한 SearchStrategyAll, SearchStrategyImage, SearchStrategyMap를 각각 모드에 따라 갈아 끼워서 사용하면 된다.
이처럼 옵션들마다의 행동들을 모듈화하여 독립적이고 상호 교체 가능하게 만든 것이다.


12. Template

어떤 같은 형식을 지닌 특정 작업들의 세부 방식을 다양화하고자 할때 사용하는 패턴
다양화된 방식을 각각 자식 클래스들에서 오버라이딩하는 방식으로 구현하는 것이다.
이는 상속과 다를바가 없어보이지만, 템플릿 메소드에서의 상속은 일정 형식이 존재한다.
부모 클래스에 전반과정을 수행하는 메인 메소드가 있고, 그 과정 가운데 세부 메소드가 존재한다. 메인 메소드를 호출하면 실행 중에 이 세부 메소드들이 호출되는 형태이다.
자식 과정에서는 그 세부 메소드를 오버라이딩한다.
어떤일을 수행하는 몇 가지 방법이 있고, 그 전반적 과정에 공통된 절차가 있을 때 코드를 효율적으로 짜기 위해 만들어졌다.

23. Visitor

데이터 구조와 처리를 분리한다.
개방-폐쇠 원칙을 적용하는 방법 중 한 가지이다.

0개의 댓글