본문 바로가기
정보처리기사/필기

[정보처리기사 필기 요약] 디자인 패턴(1) - 생성패턴

by 채연2 2021. 3. 2.

* 디자인 패턴 구성

  1. 패턴 이름 및 유형
    • 설계 의도를 표현하며 한 두 단어로 설계 문제와 해법 서술
  2. 문제 및 배경
    • 해결해야할 문제와 그 배경 설명하며 언제 패턴 사용하는지 서술
  3. 해결
    • 설계 구성 요소와 그 요소들 간 관계, 책임, 협력관계 서술
  4. 사례
    • 간단한 적용 사례 서술
  5. 결과
    • 디자인 패턴 적용해서 얻는 결과와 장단점 서술
  6. 샘플코드
    • 패턴이 적용된 원시 코드 기술

* GoF(Gang of Four) 디자인 패턴

목적 생성 패턴 구조 패턴 행위 패턴
암기 FSABP ABCD2FP T2I2C2S2MVO
의미 객체 생성방식 결정 객체 조직화 객체 행위를 조직, 관리, 연합
범위 클래스

Factory method Adapter Template method
Interpereter
객체 Singleton
Abstract factory
Builder
Prototype
Bridge
Composite
Decorator
Facade
Fly weight
Proxy
Iterator
Command
Chain of Resposibility
State
Strategy
Mediator
Memento
Visitor
Observer

 

① 생성패턴(Creation Pattern) : 객체 인스턴스 생성 위한 클래스 정의와 객체 생성 방식 구조화 캡슐화 방법 등 제공

종류 개념
Factory method - 객체 생성하기 위한 인터페이스 따로 정의하며 어떤 클래스에서 객체 생성하는 일을 서브 클래스가 담당하도록 함
- Virtual-Constructor 패턴
Singleton - 지정한 클래스 인스턴스가 반드시 한 개만 존재하도록 함
Abstract factory - 구체적인 클래스 지정 않고 관련성 갖는 객체들 집합을 생성하거나 서로 독립적인 객체들 집합 생성할 수 있는 인터페이스 제공
Builder - 복잡한 객체 생성하는 방법과 표현하는 방법 정의하는 클래스를 별도로 분리해 서로 다른 표현이라도 이를 생성할 수 있는 동일한 절차 제공
Prototype - 원본이 되는 인스턴스 사용하여 생성할 객체 종류 명시하고, 견본 복사해서 새로운 객체 생성

 

 

* Factory method 예

interface Pizza {
    public void prepare();
    public void bake();
    public void box();
}

abstract class PizzaStore {
    public Pizza orderPizza(String type) {
        Pizza pizza = createPizza(type);    // factory method 사용
        pizza.prepare();
        pizza.bake();
        pizza.box();
        return pizza;
    }

    // factory method
    abstract Pizza createPizza(String type);
}

class NYPizzaStore extends PizzaStore {
    @Override
    Pizza createPizza(String type) {
        if ("cheese".equals(type)) {
            return new NYStyleCheesePizza();
        } else if ("pepperoni".equals(type)) {
            return new NYStylePepperoniPizza();
        }
        return null;
    }
}

class ChicagoPizzaStore extends PizzaStore {
    @Override
    Pizza createPizza(String type) {
        if ("cheese".equals(type)) {
            return new ChicagoStyleCheesePizza();
        } else if ("pepperoni".equals(type)) {
            return new ChicagoStylePepperoniPizza();
        }
        return null;
    }
}

//사용
PizzaStore nyStore = new NYPizzaStore();
PizzaStore chicagoStore = new ChicagoPizzaStore();

Pizza pizza = nyStore.orderPizza("cheese");
Pizza pizza1 = chicagoStore.orderPizza("pepperoni");

 

* Singleton 예

- 전역변수 사용 않고 객체를 하나만 생성하도록 하며, 생성된 객체를 어디에서든지 참조할 수 있도록 하는 패턴

public class Printer {
	// 외부에 제공할 자기 자신의 인스턴스
	private static Printer printer = null;
	private Printer() { }
  
	// 자기 자신의 인스턴스를 외부에 제공
	public static Printer getPrinter(){
		if (printer == null) {
			// Printer 인스턴스 생성
			printer = new Printer();
		}
		return printer;
	}
  
	public void print(String str) {
		System.out.println(str);
	}
}

public class User {
	private String name;
	public User(String name) { this.name = name; }
	public void print() {
		Printer printer = printer.getPrinter();
		printer.print(this.name + " print using " + printer.toString());
	}
}

public class Client {
	private static final int USER_NUM = 5;
	public static void main(String[] args) {
		User[] user = new User[USER_NUM];
		for (int i = 0; i < USER_NUM; i++) {
			// User 인스턴스 생성
			user[i] = new User((i+1))
			user[i].print();
		}
	}
}

 

* Abstract factory 예

// 피자 원재료를 생산하는 팩토리 인터페이스
interface PizzaIngredientFactory {
	public Dough createDough();
	public Sauce createSauce();
	public Cheese createCheese();
	public Veggies[] createVeggies();
	public Pepperoni createPepperoni();
	public Clams createClams();
}

// 뉴욕 피자 가게
public class NYPizzaStore extends PizzaStore {
	protected Pizza createPizza(String item) {
		Pizza pizza = null;
		PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();

		if (item.equals("cheese")) {
			// 치즈 피자
			pizza = new CheesePizza(ingredientFactory);   // 팩토리를 주입한다
			pizza.setName("New York Style Cheese Pizza");
		} else if (item.equals("veggie")) {
			// 야채 피자
			pizza = new VeggiePizza(ingredientFactory);
			pizza.setName("New York Style Veggie Pizza");
		} else if (item.equals("clam")) {
			// 조개 피자
			pizza = new ClamPizza(ingredientFactory);
			pizza.setName("New York Style Clam Pizza");
		} else if (item.equals("pepperoni")) {
			// 페퍼로니 피자
			pizza = new PepperoniPizza(ingredientFactory);
			pizza.setName("New York Style Pepperoni Pizza");
		}
		return pizza;
	}
}

 

* Builder 예

/* Builder 인터페이스 */
class MazeBuilder {
    public :
        virtual void BuildMaze() { }
        virtual void BuildRoom(int room) { }
        virtual void BuildDoor(int roomFrom, int roomTo) { }
        virtual Maze* GetMaze() { return 0; }
    protected :
        MazeBuilder();
}

/* 표준적인 방, 문, 미로를 만드는 Builder 구현체 */
class StandardMazeBuilder : public MazeBuilder {
    public :
        StandardMazeBuilder();
        virtual void BuildMaze();
        virtual void BuildRoom(int);
        virtual void BuildDoor(int, int);

        Virtual Maze* GetMaze();
    private :
        Direction CommonWall(Room*, Room*);
        Maze* _currentMaze;
};

/* 미로는 만들지 않고 방과 문의 숫자를 세는 Builder 구현체 */
class CountingMazeBuilder : public MazeBuilder {
    public :
        CountingMazeBuilder();
        virtual void BuildMaze();
        virtual void BuildRoom(int);
        virtual void BuildDoor(int, int);
        virtual void AddWall(int, Direction);
        void GetCount(int &, int &) const;
    private :
        int _doors;
        int _rooms;
}

/* 기본 미로를 만드는 Director */
Maze* MazeGame::CreateMaze(MazeBuilder& builder) {
    builder.BuilderMaze();
    builder.BuildRoom(1);
    builder.BuildRoom(2);
    builder.BuildDoor(1, 2);

    return builder.GetMaze();
}

/* 복잡한 미로를 만드는 Director */
Maze* MazeGame::CreateComplexMaze(MazeBuilder& builder) {
    builder.BuildRoom(1);
    // ...
    builder.BuildRoom(1001);

    return builder.GetMaze();
}

//사용
Maze * maze;                    /* product */
MazeGame game;                  /* director */
StandardMazeBuilder builder;    /* builder */
game.CreateMaze(builder);
maze = builder.GetMaze();

 

* Prototype 예

public abstract class Shape implements Cloneable {
	protected Type type;
    abstract void draw();
    
    @Override
    public Object clone() throws CloneNotSupportedException {
    	Object clone = null;
        
        try {
        	clone = super.clone();
        } catch (Exception e) {
        	e.printStackTrace();
        }
        return clone;
    }
}

public class Circle extends Shape {
	public Circle() {
    	this.type = Type.CIRCLE;
    }
    
    @Override
    void draw() {
    	System.out.println("[Circle]");
    }
}

public class ShapeStore {
	private static Map<Type, Shape> shapeMap = new HashMap<Type, Shape>();
    
    public void registerShape() {
    	Rectangle rec = new Rectangle();
        Circle cir = new Circle();
        Triangle tri = new Triangle();
        
        shapeMap.put(rec.type, rec);
        shapeMap.put(cir.type, cir);
        shapeMap.put(tri.type, tri);
    }
    
    public Shape getShape(Type type) {
    	return (Shape)shapeMap.get(type).clone();
    }
}

public class Main {
	public static void main(String[] args) {
    	ShapeStore manager = new ShapeStore();
        manager.registerShape();
        
        Circle cir1 = (Circle)manager.getShape(Type.CIRCLE);
        cir1.draw();
        Circle cir2 = (Circle)manager.getShape(Type.CIRCLE);
        cir2.draw();
        
        Rectangle rec1 = (Circle)manager.getShape(Type.RECTANGLE);
        rec1.draw();
        
        Triangle tri1 = (Circle)manager.getShape(Type.TRIANGLE);
        tri1.draw();
    }
}

 

 

참고 : beomseok95.tistory.com/category/DesignPattern

320x100

댓글