퇴근5분전

쉽다면 쉽고.. 어렵다면 어려운 패턴이었음.  아직도 가끔은 헷갈리는데...

예제로 본것들중 기억에 남는것은 기자가 각 방송국을 들락 날락 거린다는 예제였던것 같다.

콤보짓 없이 비지터를 살짝쿵.. 비스므리 해보려 했더니... 좀..골때린게 나왔다. 의미상 별거 없어보이긴 하는데..
어쨌거나 저쨌거나..


방문자(Visitor)는 자기가 방문하게될 요소(Ac)에 자기를 등록하도록 Acceptor(방문자 v); 가 요구되고 이를 인터페이스로 구현된다. 
 
이 인터페이스를 통해 방문자의 .Visit( 요소 )를 호출하면서 구조(자료리스트)를 순회 하게 된다. 

단순하게 생각하자!! 

방문자는   방문하게될 대상에 자기가 들어갈 곳을(Acceptor) 요구하고 이를 통해 자기가 들어가서

방문(Visit())을 하게 되며  대상요소에 대한 처리는 Visit() 내에서 처리한다!!..

소스를 보자.. 말로는 역시 풀어내는것은 아직 표현부족으로 한계....

추가:  방문자의 문제 처리를 바꾸고자 한다면

간단히 짝수 출력라인 주석을 하면 홀수만 보이게된다... 일이 구분된다는 것이지.


  public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            Ac a1 = new Ac("a1");  // <== 각 요소들...
            Ac a2 = new Ac("a2");
            Ac a3 = new Ac("a3");
            Ac a4 = new Ac("a4");
            Ac a5 = new Ac("a5");
            Ac a6 = new Ac("a6");
            Ac a7 = new Ac("a7");
            Ac a8 = new Ac("a8");
            Ac a9 = new Ac("a9");
            Ac a10 = new Ac("a10");

            a1._ac = a10; <-- 하위 요소들 추가!!
            a10._ac = a4;
            a5._ac = a7;

            List<Ac> ls = new List<Ac>();  // <-- 비지터가 방문하게될 리스트...
            ls.Add(a1);
            ls.Add(a2);
            ls.Add(a3);
            ls.Add(a5);
            ls.Add(a6);
            ls.Add(a8);
            ls.Add(a9);
          
            Visitor v = new Visitor();
            foreach( Ac item in ls )
            v.Visit(item);  // <--- 각각 방문하게 된다.

            this.textBox1.Text = v.ToString();  // <-- 방문결과...


        }
    }


    public interface IVisitor
    {
        void Visit(Ac ac);
    }

    public interface IAcc
    {
        void Acceptor( IVisitor   v);
    }

 

    public class Ac : IAcc  // <-- 방문하게 될 대상 객체이다.
    {
        static int InstanceCount = 0;
        static void Count() { InstanceCount++; }

        int _i = 0;

        public Ac _ac = null; 
        // <-- 하위 요소가 존재시... 방문자가 순회 하게 될.. 요소로 판정하기 위해... ( 콤포짓 패턴... )

        public int I
        {
            get { return _i; }
        }

        string _name = "";
        public Ac(string __name)
        {
            Count();
            _i = InstanceCount;
            _name = __name;
        }

        #region IAcc 멤버
        public void Acceptor(IVisitor v)
        {
            v.Visit(this); // 비지터에 AC자신에 대한 처리를 맡긴다.
        }
        #endregion

        public override string ToString()
        {
            return _name;
        }
    }


    public class Visitor : IVisitor  //<-- 방문자...
    {
        StringBuilder sb = new StringBuilder();

        public void Clear()
        {
            sb.Remove(0, sb.Length);
        }

        #region IVisitor 멤버

        public void Visit(Ac ac)  //<-- 방문될 요소를 받는다.
        {
            if( ac.I % 2  == 0 )
            {
                 sb.AppendLine(" "+ac.ToString()+"(짝수)");
                 if (ac._ac == null) sb.AppendLine();
            }
            else
            {
                sb.AppendLine(" " + ac.ToString() + "(홀수)");
                if (ac._ac == null) sb.AppendLine();
            }
           
            if (ac._ac != null)
            {
                ac._ac.Acceptor(this); 
               //<-- 하위 요소가 존재시 방문등록을 한다.
                  이로써 방문자는 다시 하위 요소에 자기가 등록되면서 visit가 재귀형태로 호출된다.

            }
        }

        #endregion

        public override string ToString()
        {
            return sb.ToString();
        }
    }



 움... 이 패턴을 첨 접할때 Tree라는 개념을 알고 본터라.. 가장 처음 접했던 어려운 패턴이었다.

단순해보이면서도 왠지... 거북했던 패턴으로 기억나는데...

 가장 최근에 적용하고 사용한 방법중에 XmlHelper를 만들때

각 Element를 메모리에 올리기 위한 자료구조를 만들때 사용했었다.

Element를 받고 하위 Element를 동일한 타입으로 설정하고 추가 추가...

재귀를 통해 읽어들이고 각각 요구사항에 맞춰 파싱도 하고 출력도 하고... 


   단위객체 
  {
        단위객체[]  하위List;
        Print()
        {
             "<자기자신>" 
               foreach( 단위객체 obj in 하위List )
                    obj.Print()
             "</자기자신>"
        }
  }

대략...이랬다...

사용방법은 꾀 많다.
 
트리구조를 가지고 있는 자료구조에 적용하기 쉽기때문에...랄까?







 

'# 5) 디자인패턴(for .NET )' 카테고리의 다른 글

Commad? 응용...  (0) 2012.01.19
비지터 패턴...  (0) 2010.05.06
객체를 공부하면서... 커플링? 느슨한결합도?  (0) 2010.05.04
체인 패턴...  (0) 2010.05.04
커맨드패턴  (0) 2010.05.03


 요즘 공부를 하면서 객체간에 커플링과 느슨한결합도에 대한 다시한번더 생각하게 된다.

내가 주도하는 프로젝트에서야 내가 만든 프레임웍등을 이용할때나 위... 커플링과 느슨한결합도에 신경을 쓸까..?

프리형태의 입장인 지금은 저딴건 개나 줘버렷!!

지금껏 하루 하루 시간 쪼개서 공부해온 것들은 모두.. 내가 주도하거나 내가 주축이 되면.. 가능한것들 뿐이다.

SW공학.. 자체가 비전공자인 내가 공부해봤자라는 의미가 될수 있는듯 하다.

물론 알아두면 좋고 알아야 하는것이기도 하고... 물론 몰라도 돈버는데는 영향이 없어보인다. 


 객체와 객체를 연결지으면서 서로간에 간섭이 얼마나 일어나느냐를 커플링 척도로 보는데 이는 프리로 일하면서

관심밖에 사항이 된다. 결합도 역시.. 그렇다.

느슨하게 해주는 주체가 무엇이 될까?  인터페이스? 추상화된 기반객체?

음... 그렇다면... 내가 주가 되었을때의 이 개념들을 어떻게 써먹을지도 고민해봐야 하는데...

얼마전 완성된 프레임웍은 내부적으론 유지보수에 대한 대비를 많이 했지만.. 실제 사용에 있어서의 결합도는 거의 무시한채 작업이 되었는데... 이건 어떻게 한다?

객체가 객체를 사용하는데 있어서 직접적이 호출이 아닌 중간에 하나를 거쳐서 호출하게끔하여 실제 호출되는 객체의 변화에 조금 덜 반응할수 있도록 맞춰주는것이 결합도를 낮춰주는 방법이라고 난 생각한다.

개발자와 개발자간에 직접적인 업무교류가 아닌 중간에 PL을 거쳐 협업을 하는것 처럼...  이랄까? 비유가 좀 아닌가?

아무튼.. 사용자는 실제 호출되는 객체에 대해 모르는 편이 좋다고 본다. 곧 블랙박스가 된다.
알아야 하는것은 인터페이스.. 정도? 기반클래스에서 제공되는 메서드와 프로퍼티?랄까?

현재의 프로젝트는 인터페이스 기반에 호출이 아닌 해당 객체를 직접 호출하는 형태이다.

또한 객체를 생성하는데 있어서.. 해당 객체를 직접 생성하고 있는데 이를 분리하는것이 곧 생성패턴들을 이용 하는것인데

그런것도 없어보이고... 


느슨함과 커플링에 대한 생각은 좀더 찾아보고 고려해보아야 할 것이다.



'# 5) 디자인패턴(for .NET )' 카테고리의 다른 글

비지터 패턴...  (0) 2010.05.06
콤포지트 패턴...  (0) 2010.05.06
체인 패턴...  (0) 2010.05.04
커맨드패턴  (0) 2010.05.03
디자인 패턴 설명이 정말 쉬운곳...  (0) 2010.03.16