State Pattern(상태 패턴)?

상태변화를 가지는 주요 객체를 다룰 때 유용하게 적용해 볼 수 있는 패턴이다.

의도

객체의 내부 상태에 따라 스스로 행동을 변경할 수 있게 허가하는 패턴으로 이렇게 하면 개체는 마치 자신의 클래스를 바꾸는 것처럼 보인다.

 


 

서브클래스들이 상속 받을 State를 다음과 같이 만든다.

모두 가상 메서드로 이루어지고 각 가상 메서드는 에러처리만 하도록 만든다. 후손개체의 메서드가 사용되지 않고, 조상 개체의 메서드가 사용되면 자동으로 에러가 나도록 만든다.

State.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace StatePattern

{

    class State

    {

        public virtual bool Attack(Character character)

        {

            Console.WriteLine("공격 오류!");

            return false;

        }

        public virtual bool Move(Character character)

        {

            Console.WriteLine("이동 오류 !");

            return false;

        }

        public virtual bool Lucky(Character character)

        {

            Console.WriteLine("행운 오류!");

            return false;

        }

        public virtual void CountDown(Character character)

        {

        }

    }

}

 

 

싱글톤패턴 적용하여 시스템에 하나의 개체만 존재하도록 하였고, 생성자 캐릭터 개체를 입력 받도록 만들어주어, 나중에 상태개체를 변경해야 할 때 사용한다

 

Normal.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace StatePattern

{

    class Normal : State

    {

        private static Normal this_object;

        public static Normal get_object

        {

            get

            {

                if (this_object == null)

                {

                    this_object = new Normal();

                }

                return this_object;

            }

        }

        public override bool Attack(Character character)

        {

            Console.WriteLine("100% 공격력!!");

            character.Hp -= 40;

            if (character.Hp < 30)

            {

                character.chageState(Emergency.get_object);

            }

            return true;

        }

        public override bool Move(Character character)

        {

            Console.WriteLine("100% 이동!!");

            //character.chageState(Superman.get_object);

            return true;

        }

      

    }

}

 

 

Emergency.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace StatePattern

{

    class Emergency : State

    {

        Random rand = new Random();

        private static Emergency this_object;

        public static Emergency get_object

        {

            get

            {

                if (this_object == null)

                {

                    this_object = new Emergency();

                }

                return this_object;

            }

        }

        public override bool Attack(Character character)

        {

            int luck=0;

            Console.WriteLine("공격 75 %!!");

            luck = rand.Next(3);

            if (luck == 2)

            {

                character.chageState(Immortal.get_object);

                Immortal.before_state = this;

            }

            return true;

        }

        public override bool Move(Character character)

        {

            Console.WriteLine("이동 50%!!");

            return true;

        }

        public override bool Lucky(Character character)

        {           

            Console.WriteLine("행운 15!");

            return true;

        }

    }

}

 

 

 

※ 캐릭터를 담당 하게 될 Character  클래스를 보도록 하자Character Class 내부에 State 개체를 가지게 되는데, 이 개체는 수시로 각 상태를 담당하는 개체로 형 변환을 하게 된다.

 

Character.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace StatePattern

{

    class Character

    {

        int hp;

        private State state;

        public Character()

        {

            hp = 100;

            chageState(Normal.get_object);

        }

        public int Hp

        {

            get

            {

                return hp;

            }

            set

            {

                hp = value;

            }

        }

        public void chageState(State state)

        {

            this.state = state;

        }

        public void Move()

        {

            state.Move(this);      

        }

        public void Attack()

        {

            state.Attack(this);           

        }

        public void Lucky()

        {

            state.Lucky(this);

        }

        public void CountDown()

        {

            state.CountDown(this);

        }

        public void SuperItem()

        {

            chageState(Superman.get_object);

        }

    }

}

 

 

마지막으로 파일관리 개체를 활용하는 모듈을 작성한다. 이때 모듈은 파일관리 개체의 상태에 전혀 신경을 쓰지 않아도 된다. 그냥 메서드를 호출하여 사용하기만 하면 된다.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace StatePattern

{

    class Program

    {

        static void Main(string[] args)

        {

            Character c = new Character();

           

            c.Attack();

            c.Attack();

            c.Attack();

            c.Move();

           

            c.Attack();

            c.Attack();

            c.Attack();

            c.Attack();

            c.Attack();

            c.SuperItem();

            c.Attack();

            c.Attack();

        }

    }

}

 





'Programing > Design Pattern' 카테고리의 다른 글

State Pattern (상태패턴)  (0) 2016.11.30
템플릿 메서드  (0) 2016.11.30
전략패턴,Strategy patterns  (0) 2016.11.30



우리는 게임이든다른 것이든 이런 객체의 상태에 대해서 많이 접하게 됩니다상태에 따라서 같은 기능도 다르게 작동해야 하는데 위 그림도 그것을 나타내고 있습니다만약 우리가 상태 패턴을 모른다면 두가지 방법밖에 없습니다상태가 정수로 표현된다면switch 문으로 case를 상태로 하여 쭈욱 늘어 뜨릴 수 있고상태가 정수가 아닌 문자열이나 기타 다른 조건이라면 if, else if로 복잡하게 코딩할 수 밖에 없습니다.






캐릭터 클래스의 모든 매서드의 처리를 상태객체에게 위임합니다위임된 기능은 상태 객체의 현재 타입에 따라 다르게 처리됩니다현재 타입이란 서브클래스 타입을 말하는 것이죠. 이 자체가 상태가 됩니다위임된 처리를 수행하는 방법은 캐릭터 클래스내에서 상태 객채를 접근 가능하게 한뒤상태 객체는 캐릭터 객체를 매개변수로 받아서 처리를 구현합니다이것은 마치 캐릭터 객체를 대신 해서 동작하는 느낌입니다상태를 바꿀때도 이런 방법을 사용합니다상태 객체는 내부 데이터 변수가 없기 때문에 싱글톤으로 만들어 여러 캐릭터 객체가 이 상태객체의 기능을 공유할 수 있습니다.*플라이급 패턴



'Programing > Design Pattern' 카테고리의 다른 글

상태패턴 예제  (0) 2016.11.30
템플릿 메서드  (0) 2016.11.30
전략패턴,Strategy patterns  (0) 2016.11.30

+ Recent posts