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

+ Recent posts