using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;


namespace AdapterPattern

{

    public interface Print

    {

        void printWeak();

        void printStrong();

    }

    public class Banner

    {

        private String memo;


        public Banner(String memo)

        {

            this.memo = memo;

        }


        public void showWithParen()

        {

            Console.WriteLine("(" + memo + ")");

        }


        public void showWithAster()

        {

            Console.WriteLine("*" + memo + "*");

        }

    }


    public class PrintBanner : Banner, Print

    {

        public PrintBanner(String memo) : base(memo)

        {

        }

        public void printStrong()

        {

            showWithParen();

        }


        public void printWeak()

        {

            showWithAster();

        }

    }


    class Program

    {

        static void Main(string[] args)

        {

            Print print = new PrintBanner("TEST");

            print.printWeak();

            print.printStrong();

        }

    }

}



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

싱글턴 패턴  (0) 2016.10.19
SingletonPattern  (0) 2016.10.19
PrototypePattern  (0) 2016.10.05
BuilderPattern 실습  (0) 2016.09.28



url : http://egloos.zum.com/sakula99/v/2971297



싱글톤 패턴(Singleton Pattern)

http://sakula99.egloos.com/2971297

I. Singleton 이란?

아마 GOF의 32가지 패턴 중 가장 쉬우면서도 가장 자주 쓰이게 되며, 가장 문제가 될 소지를 가지는 패턴을 말하면 Singleton을 말할 수 있지 않을까 합니다.

먼저 Singleton 패턴의 용도는 하나의 프로그램 내에서 하나의 인스턴스만을 생성해야만 하는 상황. 예를 들어 환경설정을 관리하는 클래스나
Connection Pool, Thread Pool과 같이 풀(Pool) 형태로 관리되는 클래스의 경우 프로그램 내에서 단 하나의 인스턴스로 관리되는 것이 일반적이며, 이 때 Singleton 패턴을 적용하는 것이 일반적인 경우라고 볼수 있겠습니다. 그럼 세부적인 구현 형태를 살펴 보도록 하겠습니다.

II. Singleton 구현

Singleton 패턴의 가장 일반적인 형태는 다음과 같습니다.

singleton.bmp 

<일반적인 Singleton class diagram>

중요하게 보아야 할 곳은 생성자가 private으로 선언되어 있다는 것이죠. 이유는 간단하게도 클래스 외부에서 이 클래스를 직접 new 키워드로 생성하지 못하게 막겠다는 의미가 되겠습니다. Singleton 패턴은 설명보다는 코드로 보는 것이 훨씬 간결하므로 다음 코드를 보도록 하겠습니다.

  1. Singleton 패턴 

  2. class Singleton { 

  3. private static Singleton instance;

  4. private Singleton(){ 

  5. public static Singleton getInstance(){ 

  6. if (instance == null) 

  7. instance = new Singleton();  

  8. return instance; 

  9. }

 

   위 코드에서 파란색으로 표기된 선언부에 집중해야 합니다. Singleton 클래스의 인스턴스를 외부에서 사용하기 위해서는 항상 getInstance 메소드를 호출해야만 하도록 강제된 것을 확인하실 수 있습니다.  위와 같은 경우 getInstance가 호출될 때 객체가 생성되는데 최초 로딩 시에 객체를 생성해 두는 것이 효율적인 경우에는 다음과 같이 멤버 변수를 선언하는 곳에서 직접 생성하는 방법을 이용할 수 있습니다.

 

  1. ClassLoader에 의해 미리 인스턴스를 생성하는 방법 
  2. class Singleton { 
  3. private static Singleton instance = new Singleton(); 
  4. private Singleton(){} 
  5. public static Singleton getInstance(){ 
  6. if (instance == null) 
  7. instance = new Singleton(); 
  8. return instance; 

위의 코드에서 붉은색으로 표기된 멤버 변수 선언부를 보면 new 키워드에 의해 static으로 선언된 멤버 변수의 인스턴스를 미리 생성하는 것을 볼 수 있습니다.

다중 쓰레드 프로그래밍에 필요한 것이 아니라면 위의 코드만으로도 완성된 코드라고 볼수 있겠습니다. 미리 인스턴스를 생성할 필요가 없는 경우에는 이전의 방법을 이용하는데 그런한 방식을 lazy(게으른) 방식이라고 이야기 합니다.

다중 쓰레드 프로그래밍에서는 동기화를 이용한 적절한 수정이 필요한데 많은 커뮤니티에서 그에 따른 예제 코드가 잘 나와있습니다.

(Singleton의 다양한 형태 : http://www.anfamily.net/mcsong/70)

위의 블로그에 방문하시면 싱글톤 패턴의 다양한 종류와 그에 따른 장단점이 잘 분류되어 있습니다.

다만 좀더 자세히 내용을 들여다 보면 가장 간단한 방법이 오히려 득이 되는 경우를 찾을 수 있을 것 입니다. 다음 코드를 봐주세요.

  1. Instance의 생성은 단 한번만

  2. class Singleton{

  3. private static Singleton instance = new Singleton();

  4. private Singleton(){}

  5. public static Singleton getInstance(){

  6. return instance;

  7. }

  8. }

위의 코드의 녹색으로 표시된 부분을 봐주세요. Simple is best 라는 말 처럼 위의 코드는 Thread-safe하게 잘 만들어진 코드라고 할 수 있겠습니다.

이 클래스는 전체 라이프 타임 중에서 단 한번만 객체를 생성하고 다시는 생성하지 않습니다. 여러개의 쓰레드가 접근을 한다고 하더라도 인스턴스가 두개 이상 생성되거나 Null값을 리턴 받을 염려도 생성자가 두번 호출 되는 경우도 없죠. 

 

III. 결론

하나의 패턴은 다양한 형태로 표현되는 경우가 많습니다. 어쩔 때는 경계가 모호한 형태로 패턴이 구현되는 경우도 있지요.

이번 싱글톤 패턴은 목적과 형태가 분명한 패턴으로 항상 머리에 넣어두고 사용해야할 중요한 패턴이라고 말할 수 있습니다.

 

참고문헌

각주



검토필요


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

AdapterPattern  (0) 2016.11.09
SingletonPattern  (0) 2016.10.19
PrototypePattern  (0) 2016.10.05
BuilderPattern 실습  (0) 2016.09.28

using System;


namespace SingletonPattern

{

    class Singleton

    {

        private static Singleton _SingletoneInstance;


        private Singleton() { }


        public static Singleton _GetInstance()

        {

            if (_SingletoneInstance == null) _SingletoneInstance = new Singleton();

            return _SingletoneInstance;

        }

    }


    class Program

    {

        static void Main(string[] args)

        {

            Singleton _InstanceA = Singleton._GetInstance();

            Singleton _InstanceB = Singleton._GetInstance();

            if (_InstanceA == _InstanceB) Console.WriteLine("isEqual : " + _InstanceA + "==" + _InstanceB);


            Singleton _InstanceC = Singleton._GetInstance();

            if (_InstanceB == _InstanceC) Console.WriteLine("isEqual : " + _InstanceB + "==" + _InstanceC);


        }

    }

}



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

AdapterPattern  (0) 2016.11.09
싱글턴 패턴  (0) 2016.10.19
PrototypePattern  (0) 2016.10.05
BuilderPattern 실습  (0) 2016.09.28


using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;


namespace PrototypePattern

{

    public interface Product : ICloneable

    {

        void use(String s);


        Product createClone();

    }


    class Manager

    {

        private Dictionary<String, Object> _Dictionary = new Dictionary<String, Object>();


        public void register(String name, Product proto)

        {

            _Dictionary.Add(name, proto);

        }


        public Product create(String protoName)

        {

            Product _Product = (Product)_Dictionary[protoName];


            return _Product.createClone();

        }

    }


    class MessageBox : Product

    {

        private char _DecorationChar;


        public Object Clone()

        {

            try

            {

                return (MessageBox)this;


            }

            catch (Exception e)

            {

                throw new Exception();


            }

            finally

            {

                //omitted

            }

        }


        public MessageBox(char _DecorationChar)

        {

            this._DecorationChar = _DecorationChar;

        }


        public void use(string _String)

        {

            int length = Encoding.UTF8.GetBytes(_String).Length + 4;


            for (int i = 0; i < length; i++) Console.Write(_DecorationChar);

            Console.WriteLine("");


            Console.WriteLine(_DecorationChar + " " + _String + " " + _DecorationChar);


            for (int i = 0; i < length; i++) Console.Write(_DecorationChar);

            Console.WriteLine("");

        }


        public Product createClone()

        {

            Product _Product = null;


            try

            {

                _Product = (Product)Clone();


            }

            catch (Exception e)

            {

                e.StackTrace.ToString();


            }

            finally

            {

                //omitted

            }


            return _Product;

        }

    }


    class UnderlinePen : Product

    {

        private char _UnderlineChar;


        public Object Clone()

        {

            try

            {

                return (UnderlinePen)this;


            }

            catch (Exception e)

            {

                throw new Exception();


            }

            finally

            {

                //omitted

            }


        }


        public UnderlinePen(char _UnderlineChar)

        {

            this._UnderlineChar = _UnderlineChar;

        }


        public void use(String _String)

        {

            int length = Encoding.UTF8.GetBytes(_String).Length;


            Console.WriteLine("\"" + _String + "\"");

            Console.Write(" ");


            for (int i = 0; i < length; i++) Console.Write(_UnderlineChar);


            Console.WriteLine("");


        }


        public Product createClone()

        {

            Product _Product = null;

            try

            {

                _Product = (Product)Clone();


            }

            catch (Exception e)

            {

                e.StackTrace.ToString();


            }

            finally

            {

                //omitted

            }


            return _Product;

        }

    }


    class PrototypePattern

    {

        static void Main(string[] args)

        {

            Manager _Manager = new Manager();

            UnderlinePen _Pen = new UnderlinePen('*');

            MessageBox _Box = new MessageBox('|');


            _Manager.register("UnderlinePen", _Pen);

            _Manager.register("MessageBox", _Box);


            Product _PPen = _Manager.create("UnderlinePen");

            _PPen.use("Practice");


            Product _PBox = _Manager.create("MessageBox");

            _PBox.use("Practice");

        }

    }

}



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

AdapterPattern  (0) 2016.11.09
싱글턴 패턴  (0) 2016.10.19
SingletonPattern  (0) 2016.10.19
BuilderPattern 실습  (0) 2016.09.28

using System;

using System.Collections.Generic;

using System.IO;

using System.Linq;

using System.Text;

using System.Threading.Tasks;


namespace BuilderPattern

{

    abstract class Builder

    {

        public abstract void makeTitle(String title);

        public abstract void makeString(String str);

        public abstract void makeItems(String[] items);

        public abstract Object getResult();

    }


    class Director

    {

        private Builder builder;

        public Director(Builder builder)

        {

            this.builder = builder;

        }


        public Object construct()

        {

            builder.makeTitle("Hello");

            builder.makeString("Hi");

            builder.makeItems(new string[] {

                "Good Morning",

                "Good Afternooon",

                "Good Evening"

            });


            return builder.getResult();

        }

    }


    class TextBuilder : Builder

    {

        private String _BL = "==========";

        private String _LF = "\n";


        private String _StartPointSquare = "▣";

        private String _StartPointArrow = "→";


        private String _FileName;

        private String _FileExtension = ".txt";

        private StreamWriter _StreamWriter;


        private StringBuilder builder = new StringBuilder();


        public override void makeTitle(string title)

        {


            _FileName = title + _FileExtension;


            try

            {

                _StreamWriter = new StreamWriter(_FileName);

                _StreamWriter.WriteLine(_BL);

                _StreamWriter.WriteLine(title);

            }

            catch (IOException e)

            {

                e.StackTrace.ToString();

            }

            finally

            {

                //omitted

            }

        }


        public override void makeString(string str)

        {

            _StreamWriter.Write(_StartPointSquare);

            _StreamWriter.WriteLine(str);

        }


        public override void makeItems(string[] items)

        {

            foreach (String temp in items) _StreamWriter.WriteLine(_StartPointArrow + temp);


            _StreamWriter.WriteLine(_BL);

        }


        public override object getResult()

        {

            _StreamWriter.Close();

            return _FileName;

        }

    }


    class HTMLBuilder : Builder

    {

        private String[] _ElementPrefix = { "<html>", "<head>", "<title>", "<body>", "<h1>", "<p>", "<ul>", "<li>" };

        private String[] _ElementSuffix = { "</html>", "</head>", "</title>", "</body>", "</h1>", "</p>", "</ul>", "</li>" };


        private String _FileName;

        private String _FileExtension = ".html";

        private StreamWriter _StreamWriter;


        public override void makeTitle(string title)

        {

            _FileName = title + _FileExtension;


            try

            {

                _StreamWriter = new StreamWriter(_FileName);

            }

            catch (IOException e)

            {

                e.StackTrace.ToString();

            }

            finally

            {

                //omitted

            }


            _StreamWriter.Write(_ElementPrefix[0] + _ElementPrefix[1] + _ElementPrefix[2]);

            _StreamWriter.Write(title);

            _StreamWriter.WriteLine(_ElementSuffix[2] + _ElementSuffix[1] + _ElementSuffix[3]);


            _StreamWriter.Write(_ElementPrefix[4]);

            _StreamWriter.Write(title);

            _StreamWriter.WriteLine(_ElementSuffix[4]);

        }


        public override void makeString(string str)

        {

            _StreamWriter.Write(_ElementPrefix[5]);

            _StreamWriter.Write(str);

            _StreamWriter.WriteLine(_ElementSuffix[5]);

        }


        public override void makeItems(string[] items)

        {

            _StreamWriter.Write(_ElementPrefix[6]);


            foreach (String temp in items) _StreamWriter.Write(temp);


            _StreamWriter.WriteLine(_ElementSuffix[6]);

        }


        public override object getResult()

        {

            _StreamWriter.WriteLine(_ElementSuffix[3] + _ElementSuffix[0]);

            _StreamWriter.Close();

            return _FileName;

        }

    }


    class BuilderPattern

    {

        public static void Main(String[] argv)

        {

            if (argv.Length != 1)

            {

                usage();

                Environment.Exit(0);

            }


            if (argv[0].Equals("plain"))

            {

                Director director = new Director(new TextBuilder());

                String result = (String)director.construct();

                Console.WriteLine(result + " 생성");

            }

            else if (argv[0].Equals("html"))

            {

                Director director = new Director(new HTMLBuilder());

                String result = (String)director.construct();

                Console.WriteLine(result + " 생성");

            }

            else

            {

                usage();

                Environment.Exit(0);

            }

        }


        public static void usage()

        {

            Console.WriteLine("Usage : Main Plain.");

            Console.WriteLine("Usage : Main HTML.");

        }

    }

}

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

AdapterPattern  (0) 2016.11.09
싱글턴 패턴  (0) 2016.10.19
SingletonPattern  (0) 2016.10.19
PrototypePattern  (0) 2016.10.05

+ Recent posts