enumSingleton {
INSTANCE;
publicvoidhello() {
System.out.println("hello is called.");
}
}
* Singleton.INSTANCE라는 유일한 인스턴스가 생성됨
* Singleton.INSTANCE.hello();로 접근 가능함
📌 Flyweigth 패턴
⭐ n개의 인스턴스를 한번만 생성하고 등록하여 공유하는 패턴
싱글톤의 확장버전 ( 싱글톤은 1개 , 플라이웨이트는 n개 )
Map에 싱글톤 객체들을 등록하여 공유하는 것
싱글톤 객체들을 등록하기 떄문에 멀티쓰레드 환경에 주의해야함
해당 객체를 반환하는 메서드가 동기화 처리되있어야함
서로 다른 쓰레드가 동시에 같은 인스턴스를 사용하길 원하면 해당 인스턴스가 없는 경우 여러번 생성될 수 있음
Spring Container와 유사함
생성과 사용의 분리 ( 사용자는 사용, Factory가 생성)
스프링에서도 Bean(객체)을 등록하면 Map형태의 Container에 저장됨
사용자는 Container에서 빈을 꺼내 쓰기만 하면됨
📌 Prototype 패턴
⭐ 인스턴스를 복사해서 새 인스턴스를 만드는 패턴
왜 Prototype이 필요한 것일까?
종류가 너무 많아 클래스로 정리할 수 없는 경우
클래스 수가 많아지면 소스 프로그램을 관리하기 어려움
클래스로부터 인스턴스 생성이 어려운 경우
동일한 인스턴스 생성을 원하는 경우 클래스 사용이 아닌 인스턴스를 복사가 편함
프레임워크와 생성하는 인스턴스를 분리하고 싶은 경우
클래스 이름의 속박으로부터 프레임워크를 분리
인스턴스의 복사는 iv(인스턴스 변수)값들의 복사
얕은 복사 vs 깊은 복사
얕은 복사는 참조변수를 복사하므로 원본의 영향 O
깊은 복사는 서로 다른 객체를 참조하므로 원본의 영향 X
clone메서드는 얕은 복사에 해당됨
clone메서드는 객체의 복제를 위한 메서드
해당 인스턴스를 복제하여 새로운 인스턴스를 생성해 그 참조값을 반환함
Flyweight 패턴과의 차이점
Prototype 패턴에서는 현재 인스턴스와 동일한 상태의 별도의 인스턴스를 만들어 이용
Flyweight 패턴에서는 하나의 인스턴스를 여러 장소에서 공유하여 이용함
📌 Builder 패턴
⭐ 복잡한 메서드를 조합하여 인스턴스를 구축
Facade 패턴과 유사
복잡한 인스턴스를 생성해주는 간단한 인터페이스를 외부에 제공 -> Builder 패턴
복잡한 내부 모듈을 조합하여, 간단한 인터페이스를 외부에 제공 -> Facade 패턴
내부적으로 Bridge패턴과 Template Method패턴이 적용되어 있음
📌 Factory Method 패턴
⭐ 상위 클래스에서 인스턴스 생성 방법을 결정,하위 클래스에서 구체화
Template Method 패턴의 확장버전
상위 클래스에서 인스턴스 생성을 위한 뼈대(프레임워크)와 실제 인스턴스를 생성하는 하위클래스로 분리
Factory Method 패턴에서는 패키지 단위로 분리
변하지 않는 부분과 변하는 부분을 분리하여 추상 패키지는 1개, 구현 패키지는 n개 -> OCP 충족
static Factory Method와는 다른 것임
📌 Abstract Factory 패턴
⭐ 추상적인 '제품'을 추상적인 '부품'으로 쪼개 추상 '팩터리'를 통해 조립
Factory Method 패턴의 확장버전
복잡한 구조를 가진 인스턴스를 부품으로 쪼개 팩터리에서 인스턴스 생성 방법을 결정
추상 팩터리 패키지 1개, 구현 팩터리 패키지 n개 -> OCP 충족
구현에 집중 X -> 인터페이스에 주목
📌 Iterator 패턴
⭐ 반복문의 조건식을 분리(사용 -> 구현)
자주 변경되는 부분을 분리하여 변경에 유리한 코드를 만듬
// 루프 변수 i를 사용한 예for(inti=0; i < arr.length; i++) {
System.out.println(arr[i]);
}
<자주 변경되는 부분> arr.length// 확장 for문을 사용한 예for (inte : arr) {
System.out.println(e);
}
arr에는 배열, List, Set이 올 수 있음 ( Iterable을 구현한 인스턴스들 )
Iterator를 사용하면 구현과 분리하여 반복할 수 있음
Iterator<BooK> it = bookShelf.iterator();
while (it.hasNext()) {
Bookbook = it.next();
System.out.println(book.getName());
}
bookShelf가 집약하고 있는 것이 배열이 아닌 ArrayList를 사용하더라도 해당 while문은 변경 X
즉, 어떤 구현체가 와도 iterator메서드를 가지고 있고, 올바른 Iterator<Book>을 반환하면 됨
📌 Template Method 패턴
⭐ 상위 클래스에서 처리의 뼈대를 결정하고 하위 클래스에서 그 구체적 내용을 결정하는 패턴
변하지 않는 부분을 상위 클래스에 두고 변하는 부분을 추상메서드로 정의해둬서, 상속을 통해 완성
IoC(제어의 역전)개념을 활용
모든 종류의 작업을 사용하는 쪽에서 제어
제어권을 상위 템플릿 메서드에 넘기고, 자신이 필요할때 호출되어 사용되도록 사용하는 쪽에서 제어
전략 패턴과 차이점
템플릿 메서드 패턴은 추상클래스를 상속을 통해 완성 ( OCP = 확장 open, 변경 close)
일부 프로그램의 동작을 변경
전략 패턴은 매개변수(포함)를 주입 받아서 완성
일부를 변경하기보다는 알고리즘 전체를 모두 전환
브릿지 패턴과 차이점
템플릿 메서드 패턴은 1개의 추상메서드를 다루지만
브릿지 패턴은 n개의 추상메서드를 인터페이스로 추출하여 선언(기능)과 구현을 분리한 형태
📌 Strategy 패턴
⭐ 일련의 알고리즘(자주 변경되는 코드)을 (매개변수/생성자)를 통해 외부에서 공급받는(의존성 주입) 패턴
변하는 것과 변하지 않는 것의 분리
자주 변하는 코드를 외부로 분리하여 의존성 주입을 통해 알고리즘 전체를 변경(교체)
클라이언트에 따라 알고리즘을 독립적으로 변경 가능
브릿지 패턴과 차이점
전략패턴은 객체의 생성시점이 아닌 동작시점의 행동방식 변경에 초점을 둠, 객체는 언제든지 행동 객체의 입력에 따라 그 동작방식이 변경 될 수 있음
브릿지 패턴은 생성시점에 초점이 맞춰져 있음. 전략 패턴처럼 런타임에 행동이 변경되는 것이 아니라 객체의 생성시점에 입력으로 받는 행동객체에 따라 브리지 객체의 행동방식이 결정됨.
전략 패턴의 단점 '런타임 비용'
해결책 : 플라이웨이트 패턴(여러 콘텍스트에서 동시에 사용할 수 있는 공유 객체)을 적용
-> 새로운 콘텍스트에서 동일 전략 객체를 반복해서 적용할 떄는 새로 생성되는 비용을 줄이기 위해 즉, 기존 전략 객체가 있으면 재사용하기 위해서