DESIGN PATTERN

Factory Method Pattern VS Strategy Pattern

파란실버라이트 2013. 3. 29. 15:26
 Factory Method Pattern (Extend의 잘못 사용)이 어떤 문제를 일으키고

Strategy Pattern을 어떻게 대안이 될 수 있는가? ^^

 

- Factory Method pattern Diagram

 

 

    class FLEX :Equipment
    {
        public override void Start()
        {
            //VK93과 같은 일을 한다(중복코드 발생)
            //do someting V93K about start
        }

        public override void Load()
        {
            //CATALIST와 같은 일을 한다(중복코드 발생)
            //do someting CATALIST about load
        }

        public override void Modify()
        {
            //do someting FLEX about modify
        }
    }

 

  문제점 : VK93의 Start() or Catalist 의 Load() 함수가 변경된다면 같이 수정이 필요

 

 

    class D10 : Equipment
    {

        public override void Start()
        {
            //do someting D10 about load
        }

        public override void Load()
        {
            //do someting D10 about load
        }

        //LSP(서브타입은 언제나 자신이 기반타입으로 교체할 수 있어야 한다) 위반
        public override void Modify()
        {
            throw new NotImplementedException();
        }
    }

 

 

    public partial class Form1 : Form
    {
        EquipmentCommander _ec = new EquipmentCommander();

        public Form1()
        {
            InitializeComponent();

            Equipment vk93 = EquipmentFactory.CreateEquipment("V93K");
            Equipment Catalist = EquipmentFactory.CreateEquipment("Catalist");
            Equipment D10 = EquipmentFactory.CreateEquipment("D10");
            Equipment Flex = EquipmentFactory.CreateEquipment("FLEX");

 

            _ec.Excute(vk93);
            _ec.Excute(Catalist);
            _ec.Excute(Flex);

 

            //서브클래스 인스턴스를 파라미터로 전달 했을 때 메소드가 이상하게 작동 
            //Modify function이 제대로 구현되지 않음

             _ec.Excute(D10);
        }
    }

 

 문제점 : LSP를 위반한다. 즉 기반 클래스로 서브클래스의 사용을 하지 못한다.

 

 

 

 

 

- Strategy Pattern Diagram

  

 

 

    public class Equipment
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Location { get; set; }
        public string PropertyforManager { get; set; }

 

        //각각 Strategy 를 가지고 있다.

        public IStart start { get; set; }
        public IModify modify { get; set; }
        public ILoad load { get; set; }
    }

 

 Factory 에서 생성 시에  맞는 전략을 구현한다.

 

    class EquipmentFactory
    {
        public static Equipment CreateEquipment(string EqpName)
        {

            Equipment eqp = new Equipment();
            eqp.Name = EqpName;

            if (EqpName.Equals("V93K"))
            {
                eqp.start = new StartV93K();
                eqp.load = new LoadV93K();
                eqp.modify = new ModifyV93K();
            }
            else if (EqpName.Equals("Catalist"))
            {
                eqp.start = new StartCatalist();
                eqp.load = new LoadCatalist();
                eqp.modify = new ModifyCatalist();
            }
            else if (EqpName.Equals("D10"))
            {
                eqp.start = new StartD10();
                eqp.load = new LoadD10 ();


                //modify 가 필요없는 Equipment는 ModifyNothing을 구현한다.
                eqp.modify = new ModifyNothing();
            }
            else if (EqpName.Equals("FLEX"))
            {

                // Flex는 V93의 Start와 Catalist의 Load를 구현함으로 중복 코드의 없음
                eqp.start = new StartV93K();
                eqp.load = new LoadCatalist();
                eqp.modify = new ModifyFlex();
            }
            else
            {
                throw new Exception("unregisted Eqp Class");
            }

            return eqp;
        }
    }

 

 문제점 해결 : 전략 객체를 이용해서 장비가 행위를 한다.

                      중복코드를 만들지 않는다.(수정이 필요하면 전략객체만을 수정하면 된다.)

                      새로운 행위가 필요하면 기반 클래스의 수정없이 전략 클래스를 확장(OCP를 지킴)

 

 

    public partial class Form1 : Form
    {
        EquipmentCommander _ec = new EquipmentCommander();

        public Form1()
        {
            InitializeComponent();

            Equipment vk93 = EquipmentFactory.CreateEquipment("V93K");
            Equipment Catalist = EquipmentFactory.CreateEquipment("Catalist");
            Equipment D10 = EquipmentFactory.CreateEquipment("D10");
            Equipment Flex = EquipmentFactory.CreateEquipment("FLEX");

            _ec.Excute(vk93);
            _ec.Excute(Catalist);
            _ec.Excute(Flex);

 

             //D10은 modify를 하지 않지만 ModifyNothing()을 구현해서 문제를 해결한다.

=> Equipment Generator Code 

 

            else if (EqpName.Equals("D10"))
            {
                eqp.start = new StartD10();
                eqp.load = new LoadD10 ();


                eqp.modify = new ModifyNothing();
            }

 

_ec.Excute(D10);

 

 

            //Flex장비의 행동을vk93과 같게 변경하고 싶다면??
            //클래스를 생성해서 위임해야 겠지만 예제 이므로 여기서 테스트 하였음
            Flex.start = new StartV93K();
            Flex.load = new LoadV93K();
            Flex.modify = new ModifyV93K();

            _ec.Excute(Flex);

 

 

  }

}

 

문제점 해결 : EquipmentCommander 의 Execute가 기반 타입으로 작동하는데 문제가 없다

                     즉 LSP를 위반하지 않는다 ^^

 

 

FactoryMethodPattern.zip