객체의 결합을 통해 기능을 동적으로 유연하게 확장 하게 해주는 패턴
public class DecoratorPattern {
public static void main(String[] args) {
new XWingFighter().attack();
// 탄환 발사
new LaserDecorator(new XWingFighter()).attack();
// 탄환 발사
// 레이저 발사
new PlasmaDecorator(
new MissileDecorator(
new LaserDecorator(
new XWingFighter()
))).attack();
// 탄환 발사
// 레이저 발사
// 미사일 발사
// 플라즈마 발사
}
}
///////////////////////////////////////////////////////////
public interface Fighter {
public void attack ();
}
public class XWingFighter implements Fighter {
@Override
public void attack () {
System.out.println("탄환 발사");
}
}
///////////////////////////////////////////////////////////
public abstract class FighterDecorator implements Fighter {
private Fighter decoratedFighter;
public FighterDecorator(Fighter _decoratedFighter) {
decoratedFighter = _decoratedFighter;
}
@Override
public void attack () {
decoratedFighter.attack();
}
}
public class LaserDecorator extends FighterDecorator {
public LaserDecorator (Fighter _decoratedFighter) {
super(_decoratedFighter);
}
@Override
public void attack () {
super.attack();
System.out.println("레이저 발사");
}
}
코드를 살펴보면 추상클래스로 선언된 FighterDecorator 는 LaserDecorator 가 상속하는 형태이다. 때문에 attack()
함수는 오버라이딩 되어있다.
DecoratorPattern 클래스에서 new LaserDecorator(new XWingFighter()).attack();
이부분은 생성자 부분에 XwingFighter 넣고 attack()
함수를 실행하게 되면 XwingFighter 부분의 attack()
함수 실행후 LaserDecorator 부분의 attack()
함수가 실행되는 것을 볼 수 있다.
팩토리 메소드 패턴은 객체를 생성할 때 어떤 클래스의 인스턴스를 만들지 서브 클래스에서 결정하게 하는 것이다.
abstract class Component {
protected abstract String getCompName ();
public Component () {
System.out.println(this.getCompName() + " 생성");
}
}
class Button extends Component {
@Override
protected String getCompName() { return "버튼"; }
}
class Switch extends Component {
@Override
protected String getCompName() { return "스위치"; }
}
class Dropdown extends Component {
@Override
protected String getCompName() { return "드랍다운"; }
}
////////////////////////////////////////////////////
class Console {
private CompFactory compFactory = new CompFactory();
Component comp1;
Component comp2;
Component comp3;
void withFactory () {
comp1 = compFactory.getComp(Usage.PRESS);
comp2 = compFactory.getComp(Usage.TOGGLE);
comp3 = compFactory.getComp(Usage.EXPAND);
}
}
enum Usage {
PRESS, TOGGLE, EXPAND
}
코드를 살펴보면 withFactory()
함수가 실행되면 인자로 생성될 객체의 조건을 넣어주며 Compfactyory 클래스에서 객체를 생성해 반환해 주는 것을 볼 수 있다.
Component 추상클래스로 정의되어 자식클래스들은 getCompname()
을 오버라이드 하고 있다.
모든 클래스 간의 복잡한 로직을 캡슐화하여 하나의 클래스에 위임하여 처리하는 패턴이다.
즉, M:N 관계에서 M:1 관계로 복잡도를 떨어뜨려 유지 보수 및 재사용의 확장성에 유리한 패턴이다.
public class ModeMediator {
ArrayList<ModeListener> listeners = new ArrayList<>();
public void addListener(ModeListener listener) {
listeners.add(listener);
}
public void onModeChange (Mode mode) {
for (ModeListener listener : listeners) {
listener.onModeChange(mode);
}
}
}
public class ModeSwitch {
Mode mode = Mode.LIST;
ModeMediator modeMediator;
public void setModeMediator (ModeMediator _modeMediator) {
modeMediator = _modeMediator;
}
public void toggleMode () {
mode = mode == Mode.LIST ? Mode.GALLERY : Mode.LIST;
if (modeMediator != null) {
modeMediator.onModeChange(mode);
}
}
}
enum Mode { LIST, GALLERY }
public interface ModeListener {
public void onModeChange (Mode mode);
}
class ListView implements ModeListener {
@Override
public void onModeChange(Mode mode) {
System.out.println(
"리스트뷰 " + (mode == Mode.LIST ? "보여줌" : "감춤")
);
}
}
class GalleryView implements ModeListener {
@Override
public void onModeChange(Mode mode) {
System.out.println(
"갤러리뷰 " + (mode == Mode.GALLERY ? "보여줌" : "감춤")
);
}
}
class DataDownloader implements ModeListener {
@Override
public void onModeChange(Mode mode) {
System.out.println(
(mode == Mode.LIST ? "리스트" : "갤러리")
+ "뷰용 데이터 다운로드");
}
}
코드를 살펴보면 ListView, GalleryView, DataDownloader 클래스들을 ModeListener 인터페이스를 상속한다.
ModeMediator 클래스에서는 onModeChange()
함수를 통해서 ModeListener 인터페이스를 상속한 하위 클래스들을 MediatorPattern 클래스의 addListener(new ListView())
함수를 통해 기능을 호출하고 있다.
ModeSwitch 클래스는 ModeMediator setModeMediator
함수를 통해 객체를 넣어준다.
Composite 패턴이란 특정 클래스의 객체들을 트리 관계로 다루고 포함하는 객체와 포함되는 객체를 같은 인터페이스로 다루는 패턴이다.
, 다음과 같이 정의된다. 복합 객체와 단일 객체의 처리방법이 다르지 않을경우
Directroy-File
관계에 쓰인다. Tree
형태로 내부가지를 탐색 및 삭제를 진행한다. 코드의 구현예시는 설명으로 충분하기에 생략한다.