200p - 디자인 패턴은 객체 지향의 특성 중 00(extends), 00000(interface/implements), 00(객체를 속성으로 사용)을 이용한다.
상속, 인터페이스, 합성
201p - 어댑터 패턴은 00 00 00을 활용한 설계 패턴이라고 할 수 있다.
개방 폐쇄의 원칙
실제 개발 현장에서 비즈니스 요구 사항을 프로그래밍으로 처리하면서 만들어진 다양한 해결책 중에서, 많은 사람들이 인정한 베스트 프랙티스를 정리한 것이다.
- 객체지향 특성과 설계 원칙을 기반으로 구현돼 있다.
변환기(converter), 서로 다른 두 인터페이스 사이에 통신이 가능하게 하는 것.
호출 당하는 쪽의 메서드를 호출하는 쪽의 코드에 대응하도록 중간에 변환기를 통해 호출하는 패턴

1) 대리자를 사용하지 않고 직접 호출하는 구조

2) 프록시 패턴이 적용된 경우
실제 서비스 객체가 가진 메서드와 같은 이름의 메서드를 사용하는데, 이를 위해 인터페이스를 사용한다.
인터페이스를 사용하면 서비스 객체가 들어갈 자리에 대리자 객체를 대신 투입해 클라이언트 쪽에서는 실제 서비스 객체를 통해 메서드를 호출하고 반환값을 받는지, 대리자 객체를 통해 메서드를 호출하고 반환값을 받는지 전혀 모르게 처리할 수도 있다.


대리자는 실제 서비스와 같은 이름의 메서드를 구현한다. 이때 인터페이스를 사용한다.
대리자는 실제 서비스에 대한 참조 변수를 갖는다. (합성)
대리자는 실제 서비스의 같은 이름을 가진 메서드를 호출하고, 그 값을 클라이언트에게 돌려준다.
대리자는 실제 서비스의 메서드 호출 전후에 별도의 로직을 수행할 수도 있다.
프록시 패턴
- 제어 흐름을 조정하기 위한 목적으로 중간에 대리자를 두는 패턴
또한 인터페이스를 중간에 두고 스노우타이어와 일반 타이어, 광폭 타이어를 서로 교체해 줘도 영향받지 않았던 자동차를 예로 들었던 의존 역전의 원칙(DIP)도 적용된 설계 패턴이라 볼 수 있겠다.
![]() | ![]() |
도장/도배업자를 의미한다.
장식자: 원본에 장식을 더하는 패턴
프록시 패턴과 구현 방법이 같다.
다만 프록시 패턴은 클라이언트가 최종적으로 돌려받는 반환값을 조작하지 않고 그대로 전달하는 반면, 데코레이터 패턴은 클라이언트가 받는 반환값에 장식을 덧입힌다.
| 프록시 패턴 | 데코레이터 패턴 |
|---|---|
| 제어의 흐름을 변경하거나 별도의 로직 처리를 목적으로 한다. | 클라이언트가 받는 반환값에 장식을 더한다. |
| 클라이언트가 받는 반환값을 특별한 경우가 아니면 변경하지 않는다. | - |

- 장식자는 실제 서비스와 같은 이름의 메서드를 구현한다. 이때 인터페이스를 사용한다.
- 장식자는 실제 서비스에 대한 참조변수를 갖는다. (합성)
- 장식자는 실제 서비스의 같은 이름을 가진 메서드를 호출, 그 반환값에
장식을 더해 클라이언트에게 돌려준다.- 장식자는 실제 서비스의 메서드 호출 전후에 별도의 로직을 수행할 수도 잇다.
데코레이터 패턴
- 메서드 호출의 반환값에 변화를 주기 위해 중간에 장식자를 두는 패턴
- 클래스의 인스턴스, 즉 객체를 하나만 만들어 사용하는 패턴
인스턴스를 하나만 만들어 사용하기 위한 패턴이다.
- new를 실행할 수 없도록 생성자에 private 접근 제어자를 지정한다.
- 유일한 단일 객체를 반환할 수 있는 정적 메서드가 필요하다.
- 유일한 단일 객체를 참조할 수 있는 정적 참조 변수가 필요하다.


단일 객체인 경우 결국 공유 객체로 사용되기 때문에 속성을 갖지 않게 하는 것이 정석이다. 단일 객체가 속성을 갖게 되면 하나의 참조변수가 변경한 단일 객체의 속성이 다른 참조 변수에 영향을 미치기 때문이다.
👉 전역/공유 변수를 가능한 한 사용하지 말라는 지침과 일맥상통한다.

참조하고 있는 객체의 toString() 메서드가 호출된다. 별도 오버라이딩 하지 않았다면, 객체의 고유 값인 hashcode를 반환하게 된다.
s1, s2, s3가 동일한 객체를 참조한다는 것을 의미한다.
싱글톤 패턴의 특징
- private 생성자를 갖는다.
- 단일 객체 참조 변수를 정적 속성으로 갖는다.
- 단일 객체 참조 변수가 참조하는 단일 객체를 반환하는 getInstance() 정적 메서드를 갖는다.
- 단일 객체는 쓰기 가능한 속성을 갖지 않는 것이 정석이다.
- 상위 클래스의 견본 메서드에서 하위 클래스가 오버라이딩한 메서드를 호출하는 패턴이다.



상위 클래스에 공통 로직을 수행하는 템플릿 메서드와,
하위 클래스에 오버라이딩을 강제하는 추상 메서드 또는 선택적으로 오버라이딩 할 수 있는 훅(Hook) 메서드를 두는 패턴을 템플릿 메서드 패턴이라고 한다.

객체를 생성 반환하는 메서드를 말한다.

오버라이드된 메서드가 객체를 반환하는 패턴
- 의존 역전의 원칙을 활용하고 있음을 알 수 있다.
- 전략 메서드를 가진 전략 객체
- 전략 객체를 사용하는 컨텍스트(전략 객체의 사용자/소비자)
- 전략 객체를 생성해 컨텍스트에 주입하는 클라이언트(제 3자, 전략 객체의 공급자)




-템플릿 메서드 패턴과 유사하다.

단일 상속만이 가능한 자바 언어에서는 상속이라는 제한이 있는 템플릿 메서드 패턴보다는 전략 패턴이 더 많이 활용된다.



활 대신 도끼를 쓴다는 것 외에 실행 결과는 기존 전략 패턴과 차이가 없다.
코드를 보면 많은 부분에서 중복되는 것을 볼 수 있다.
Strategy.java의 코드는 동일하다.


전략을 익명 내부 클래스로 구현한 전략 패턴
- 개방 폐쇄의 원칙(OCP)와 의존 역전 원칙(DIP)이 적용된 설계 패턴이다.
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 이벤트 발생 시 실행되는 코드
}
});
// 명시적인 내부 클래스
class Outer {
private int outerField = 10;
// 멤버 내부 클래스
class Inner {
public void display() {
System.out.println("OuterField: " + outerField);
}
}
public void callInner() {
Inner innerObject = new Inner();
innerObject.display();
}
}
// 익명 내부 클래스
interface Greeting {
void greet();
}
class Outer {
public void displayGreeting() {
Greeting greeting = new Greeting() {
public void greet() {
System.out.println("Hello, this is an anonymous inner class!");
}
};
greeting.greet();
}
}
😉ChatGpt왈
- 일반적으로 자바에서 인터페이스는 직접적으로 객체로 생성될 수 없습니다. 인터페이스는 구현이 제공되지 않은 추상적인 메서드들의 집합이기 때문에, 인터페이스를 직접적으로 인스턴스화하는 것은 불가능합니다.
- 그러나 익명 내부 클래스를 사용하여 인터페이스를 구현하는 객체를 생성할 수 있습니다.
- 익명 내부 클래스는 인터페이스나 추상 클래스를 사용하여 즉석에서 구현하고 인스턴스화할 수 있는 방법을 제공합니다.
interface Greeting {
void greet();
}
class Example {
public void displayGreeting() {
Greeting greeting = new Greeting() { // 익명 내부 클래스
public void greet() {
System.out.println("Hello, this is an anonymous inner class!");
}
};
greeting.greet();
}
}
요약하자면, 인터페이스는 직접 객체로 생성될 수는 없지만, 익명 내부 클래스를 활용하여 해당 인터페이스를 구현한 객체를 생성할 수 있습니다.