ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [디자인 패턴] 13. 추상 팩토리 패턴 (Abstract Factory Design Pattern)
    Computer Science/Design Pattern 2022. 12. 20. 02:20
    728x90

    학습목표

    • 관련된 여러 클래스의 객체를 생성하는 코드의 캡슐화 방법
    • 추상 팩토리 패턴 이용 관련 객체의 생성 방법 이해

    추상 팩토리 패턴 (Abstract Factory Pattern)

    관련성이 있는 여러 종류의 객체들을 일관된 방식으로 생성할 때 유용한 패턴이다.

     

    클라이언트는 캡슐화된 추상 팩토리를 접근하여 Product가 변경되더라도 클라이언트는 알 수 없다.


    팩토리 메서드 패턴 vs 추상 팩토리 패턴

    팩토리 메서드 패턴

    • 조건에 따른 객체 생성을 팩토리 클래스로 위임하여, 팩토리 클래스에서 객체를 생성하는 패턴

    추상 팩토리 패턴

    • 서로 관련이 있는 객체들을 통째로 묶어서 팩토리 클래스로 만들고, 이들 팩토리를 조건에 따라 생성하도록 다시 팩토리를 만들어서 객체를 생성하는 패턴
    • 추상 팩토리 패턴은 팩토리 메서드 패턴을 더 캡슐화한 방식이라 볼 수 있다.

    하지만 추상 팩토리 패턴이 팩토리 메서드 패턴의 상위 호환이 아니고, 두 패턴 간 차이가 명확하기 때문에 상황에 따라 적절한 패턴을 적용해야 한다.

     

     

    추상 팩토리 패턴 실습

    컴퓨터 제조 공장

    컴퓨터 생산 공장에서 컴퓨터(노트북)의 각 부품들 마우스, 키보드, 모니터는 같은 제조사의 제품으로 구성된다.

    즉, Samsung Computer 객체는 일관적으로 생산해야 한다.

    제조사를 선택하는 조건은 팩토리 메서드 패턴과 같이 조건에 따라 객체를 생성하는 부분을 Factory 클래스로 정의한다.

     

    팩토리 메서드 패턴을 사용할 경우의 문제점

    public class Client {
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		ComputerFactory cFactory = new ComputerFactory();
    		//cFactory.createComputer("Samsung");
    		cFactory.createComputer("LG");
    	}
    }
    //부품 추가될 때마다 팩토리도 만들어야하므로, 코드의 지속적 수정 발생 (OCP 위반)
    public class ComputerFactory {
    	public void createComputer(String type) {
    		KeyboardFactory kFactory = new KeyboardFactory();//팩토리 객체 생성
    		MouseFactory mFactory = new MouseFactory();
    		
    		kFactory.createKeyboard(type); //각 타입에 맞는 하위 객체 생성
    		mFactory.createMouse(type);
    		
    		System.out.println("----" + type + " 컴퓨터 완성 ----");
    	}
    }
    public class KeyboardFactory {
    	//조건에 따른 객체 생성 메소드
    	public Keyboard createKeyboard(String type) {
    		Keyboard keyboard = null;
    		
    		switch(type) {
    		
    		case "LG" :
    			keyboard = new LGKeyboard();
    			break;
    		case "Samsung":
    			keyboard = new SamsungKeyboard();
    			break;
    		}
    		
    		return keyboard;
    	}
    }
    public class MouseFactory {
    	public Mouse createMouse(String type) {
    		Mouse mouse = null;
    		
    		switch(type) {
    		case "LG":
    			mouse = new LGMouse();
    			break;
    			
    		case "Samsung":
    			mouse = new SamsungMouse();
    			break;
    		}
    		
    	return mouse;
    	}
    }
    public interface Keyboard {}
    public class LGKeyboard implements Keyboard{
    
    	public LGKeyboard() {
    		System.out.println("LG 키보드 생성");
    	}
    }
    public class SamsungKeyboard implements Keyboard{
    
    	public SamsungKeyboard() {
    		System.out.println("삼성 키보드 생성");
    	}
    }
    public interface Mouse {}
    public class LGMouse implements Mouse{
    	public LGMouse() {
    		System.out.println("LG 마우스 생성");
    	}
    }
    public class SamsungMouse implements Mouse{
    	public SamsungMouse() {
    		System.out.println("삼성 마우스 생성");
    	}
    }

    실행 결과

    만약, 컴퓨터 구성품 본체, 모니터, 스피커, 프린터 등등이 늘어날수록 해당 클래스를 정의해야 하고,

    ComputerFactory에서 다음 코드와 같이 각각의 팩토리 클래스 객체들을 생성하여 컴퓨터가 완성될 것이다.

    public class ComputerFactory {
        public void createComputer(String type){
            KeyboardFactory keyboardFactory = new KeyboardFactory();
            MouseFactory mouseFactory = new MouseFactory();
            BodyFactory bodyFactory = new BodyFactory();
            MonitorFactory monitorFactory = new MonitorFactory();
            SpeakerFactory speakerFactory = new SpeakerFactory();
            PrinterFactory printerFactory = new PrinterFactory();
    
            keyboardFactory.createKeyboard(type);
            mouseFactory.createMouse(type);
            bodyFactory.createBody(type);
            monitorFactory.createMonitor(type);
            speakerFactory.createSpeaker(type);
            printerFactory.createPrinter(type);
            System.out.println("--- " + type + " 컴퓨터 완성 ---");
        }
    }

    하지만, 제조사별로 구성품이 모두 같은 경우 각 컴퓨터 구성품을 Samsung, LG 구분할 필요 없이

    Samsung 컴퓨터를 만들고자 한다면 구성품이 모두 Samsung이 되도록 일관된 방식으로 객체를 생성해야 할 필요가 있다.

     

    또한 구성품이 계속 늘어날 경우 팩토리 객체를 생성하는 코드가 길어진다.

    따라서, 추상 팩토리 패턴을 이용하여 개선할 수 있다.

     

    추상 팩토리 패턴 적용

    SamsungComputerFactory, LGComputerFactory 클래스를 정의하고, 이들을 캡슐화하는 ComputerFactory 인터페이스를 하여 각 클래스는 자신의 제조사 부품 객체를 생성하도록 한다.

     

    또한 FactoryOfComputerFactory 클래스는 이전 ComputerFactory 클래스와 하는 일이 같으며, 어떤 제조사의 컴퓨터 객체를 생성할지를 결정한다. 즉, 부품이 아닌 제조사에 따른 컴퓨터 객체를 생성한다.

     

    public class SamsungComputerFactory implements ComputerFactory{
    	public SamsungKeyboard createKeyboard() {
    		return new SamsungKeyboard();
    	}
    	public SamsungMouse createMouse() {
    		return new SamsungMouse();
    	}
    }
    public class LGComputerFactory implements ComputerFactory{
    	public LGKeyboard createKeyboard() {
    		return new LGKeyboard();
    	}
    	public LGMouse createMouse() {
    		return new LGMouse();
    	}
    }
    public interface ComputerFactory {
    	public Keyboard createKeyboard();
    	public Mouse createMouse();
    }
    public class FactoryOfComputerFactory { //ComputerFactory와 같은 역할.
    	public void createComputer(String type) {//어떤 제조사 컴퓨터 객체를 만들지 결정. (각 부품X)
    		ComputerFactory cFactory = null;
    		switch(type) {
    		case "LG":
    			cFactory = new LGComputerFactory();
    			break;
    			
    		case "Samsung":
    			cFactory = new SamsungComputerFactory();
    			break;
    		}
    	cFactory.createKeyboard();
    	cFactory.createMouse();
    	System.out.println("----" + type + " 컴퓨터 완성 ----");
    	}
    } //컴퓨터 타입만 결정되면 한번에 하위 부품까지 생성
    public class Client {
    	public static void main(String[] args) {
    		FactoryOfComputerFactory factoryOfComputerFactory = new FactoryOfComputerFactory();
    		//factoryOfComputerFactory.createComputer("LG");
    		factoryOfComputerFactory.createComputer("Samsung");
    	}
    }
    // 구성품이 제조사별로 일정하므로 추상팩토리 패턴 이용 관련된 객체들을 한번에 캡슐화해서 팩토리로 만들고, 일관되게 객체를 생성함.

    결과적으로, 추상 팩토리 패턴을 이용하여 관련된 객체들을 한번에 캡슐화했고 팩토리로 만들어 일관된 객체를 생성하도록 했다.

     

     

    reference

    https://victorydntmd.tistory.com/300

     

    728x90
    반응형

    댓글

Keydi's Tistory