수색…


비고

창조적 인 패턴은 시스템을 객체가 어떻게 생성되고, 구성되고, 표현되는지를 분리하는 것을 목표로합니다. 객체 생성의 대상, 대상, 방법 및 시점에 따라 시스템의 유연성이 향상됩니다. 창조적 인 패턴은 시스템이 사용하는 클래스에 대한 지식을 캡슐화하지만, 이들 클래스의 인스턴스가 어떻게 생성되고 결합되는지에 대한 세부 사항을 숨 깁니다. 프로그래머들은 상속 시스템을 구성하면 시스템이 너무 경직된다는 것을 깨닫게되었습니다. 창조 패턴은이 가까운 결합을 깨기 위해 고안되었습니다.

싱글 톤 패턴

싱글 톤 패턴은 클래스 생성을 정확히 하나의 단일 인스턴스로 제한하도록 설계되었습니다.

이 패턴은 다음 중 하나만있는 시나리오에서 사용됩니다.

  • 다른 객체의 상호 작용을 조율하는 단일 클래스, 예. 관리자 클래스
  • 고유 한 단일 리소스를 나타내는 하나의 클래스, 예 : 로깅 구성 요소

Singleton 패턴을 구현하는 가장 일반적인 방법 중 하나는 CreateInstance() 또는 GetInstance() (또는 C #, Instance 의 정적 속성 GetInstance() 와 같은 정적 팩터 리 메서드를 사용 하는 것입니다. 그러면이 Instance 는 항상 동일한 인스턴스를 반환하도록 설계됩니다.

메서드 또는 속성에 대한 첫 번째 호출은 Singleton 인스턴스를 만들고 반환합니다. 그런 다음 메서드는 항상 동일한 인스턴스를 반환합니다. 이렇게하면 싱글 톤 객체의 인스턴스가 하나만 존재합니다.

new 를 통한 인스턴스 생성을 방지하려면 클래스 생성자를 private. 로 만들어야합니다 private.

다음은 C #에서 싱글 톤 패턴을 구현하기위한 일반적인 코드 예제입니다.

class Singleton
{
    // Because the _instance member is made private, the only way to get the single 
    // instance is via the static Instance property below. This can also be similarly 
    // achieved with a GetInstance() method instead of the property.
    private static Singleton _instance = null;

    // Making the constructor private prevents other instances from being 
    // created via something like Singleton s = new Singleton(), protecting
    // against unintentional misuse.
    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get 
        {
            // The first call will create the one and only instance.
            if (_instance == null)
            {
                _instance = new Singleton();
            }

            // Every call afterwards will return the single instance created above.
            return _instance;
        }
    }
}

이 패턴을 자세히 설명하기 위해 아래 코드는 Instance 속성이 두 번 이상 호출 될 때 Singleton의 동일한 인스턴스가 반환되는지 여부를 확인합니다.

class Program
{
    static void Main(string[] args)
    {
        Singleton s1 = Singleton.Instance;
        Singleton s2 = Singleton.Instance;
        
        // Both Singleton objects above should now reference the same Singleton instance.
        if (Object.ReferenceEquals(s1, s2))
        {
            Console.WriteLine("Singleton is working");
        }
        else
        {
            // Otherwise, the Singleton Instance property is returning something 
            // other than the unique, single instance when called.
            Console.WriteLine("Singleton is broken");
        }
    }
}

주 :이 구현은 thread 세이프가 아닙니다.

이 스레드로부터 안전하게 만드는 방법을 포함하여 더 많은 예제를 보려면 Singleton Implementation을 방문하십시오.

싱글 톤은 개념적으로 글로벌 값과 유사하며 유사한 디자인 결함과 우려를 일으 킵니다. 이 때문에 싱글 톤 패턴은 널리 안티 패턴으로 간주됩니다.

"싱글턴에 관해서 나쁘지 않은가?" 사용시 발생하는 문제에 대한 자세한 내용은

C #에서는 클래스를 static 으로 만들어 모든 멤버를 정적으로 만들 수 있으며 클래스를 인스턴스화 할 수 없습니다. 이 점을 감안할 때, 싱글 톤 패턴 대신 정적 클래스를 사용하는 것이 일반적입니다.

두 가지 주요 차이점에 대해서는 C # Singleton Pattern vs. Static Class를 참조하십시오 .

공장 방법 패턴

공장 방식은 창조적 인 디자인 패턴 중 하나입니다. 정확한 결과 유형을 지정하지 않고 객체를 만드는 문제를 처리하는 데 사용됩니다. 이 문서는 Factory Method DP를 올바르게 사용하는 방법을 알려줍니다.

간단한 예를 들어 당신에게 그 아이디어를 설명해 드리겠습니다. 전류계, 전압계 및 저항계의 세 가지 유형의 장치를 생산하는 공장에서 일하고 있다고 가정 해보십시오. 선택한 장치를 만들 수있는 중앙 컴퓨터 용 프로그램을 작성하고 있지만 보스의 생산 결정에 대해서는 최종 결정을 모릅니다.

모든 장치가 가지고있는 몇 가지 공통적 인 기능을 가진 인터페이스 IDevice 장치를 만들어 보겠습니다.

public interface IDevice
{
    int Measure();
    void TurnOff();
    void TurnOn();
}

이제 디바이스를 나타내는 클래스를 생성 할 수 있습니다. 이러한 클래스는 IDevice 인터페이스를 구현해야합니다.

public class AmMeter : IDevice
{
    private Random r = null;
    public AmMeter()
    {
        r = new Random();
    }
    public int Measure() { return r.Next(-25, 60); }
    public void TurnOff() { Console.WriteLine("AmMeter flashes lights saying good bye!"); }
    public void TurnOn() { Console.WriteLine("AmMeter turns on..."); }
}
public class OhmMeter : IDevice
{
    private Random r = null;
    public OhmMeter()
    {
        r = new Random();
    }
    public int Measure() { return r.Next(0, 1000000); }
    public void TurnOff() { Console.WriteLine("OhmMeter flashes lights saying good bye!"); }
    public void TurnOn() { Console.WriteLine("OhmMeter turns on..."); }
}
public class VoltMeter : IDevice
{
    private Random r = null;
    public VoltMeter()
    {
        r = new Random();
    }
    public int Measure() { return r.Next(-230, 230); }
    public void TurnOff() { Console.WriteLine("VoltMeter flashes lights saying good bye!"); }
    public void TurnOn() { Console.WriteLine("VoltMeter turns on..."); }
}

이제 factory 메소드를 정의해야합니다. static 메소드를 내부에 가진 DeviceFactory 클래스를 생성 DeviceFactory 봅시다 :

public enum Device
{
    AM,
    VOLT,
    OHM
}
public class DeviceFactory
{
    public static IDevice CreateDevice(Device d)
    {
        switch(d)
        {
            case Device.AM: return new AmMeter();
            case Device.VOLT: return new VoltMeter();
            case Device.OHM: return new OhmMeter();
            default: return new AmMeter();
        }
    }
}

큰! 코드를 테스트 해 봅시다.

public class Program
{
    static void Main(string[] args)
    {
        IDevice device = DeviceFactory.CreateDevice(Device.AM);
        device.TurnOn();
        Console.WriteLine(device.Measure());
        Console.WriteLine(device.Measure());
        Console.WriteLine(device.Measure());
        Console.WriteLine(device.Measure());
        Console.WriteLine(device.Measure());
        device.TurnOff();
        Console.WriteLine();

        device = DeviceFactory.CreateDevice(Device.VOLT);
        device.TurnOn();
        Console.WriteLine(device.Measure());
        Console.WriteLine(device.Measure());
        Console.WriteLine(device.Measure());
        Console.WriteLine(device.Measure());
        Console.WriteLine(device.Measure());
        device.TurnOff();
        Console.WriteLine();

        device = DeviceFactory.CreateDevice(Device.OHM);
        device.TurnOn();
        Console.WriteLine(device.Measure());
        Console.WriteLine(device.Measure());
        Console.WriteLine(device.Measure());
        Console.WriteLine(device.Measure());
        Console.WriteLine(device.Measure());
        device.TurnOff();
        Console.WriteLine();
    }
}

다음은이 코드를 실행 한 후 표시되는 출력 예입니다.

AmMeter가 켜지면 ...

36

6

33

43

24

AmMeter가 작별 인사를하는 등 깜박입니다!

VoltMeter가 켜짐 ...

102

-61

85

138

36

VoltMeter가 작별 인사를하는 등 깜박입니다!

OhmMeter가 켜집니다 ...

723828

368536

685412

800266

578595

OhmMeter가 작별 인사를하는 등 깜박입니다!

작성자 패턴

동일한 구성 프로세스가 서로 다른 표현을 생성 할 수 있도록 복잡한 객체의 구조를 표현과 분리하고 객체의 어셈블리에 대한 높은 수준의 제어를 제공합니다.

이 예제에서는 다른 차량이 단계적으로 조립되는 Builder 패턴을 보여줍니다. Shop은 VehicleBuilders를 사용하여 일련의 순차적 인 단계로 다양한 차량을 구성합니다.

using System;
using System.Collections.Generic;
 
namespace GangOfFour.Builder
{
  /// <summary>
  /// MainApp startup class for Real-World 
  /// Builder Design Pattern.
  /// </summary>
  public class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    public static void Main()
    {
      VehicleBuilder builder;
 
      // Create shop with vehicle builders
      Shop shop = new Shop();
 
      // Construct and display vehicles
      builder = new ScooterBuilder();
      shop.Construct(builder);
      builder.Vehicle.Show();
 
      builder = new CarBuilder();
      shop.Construct(builder);
      builder.Vehicle.Show();
 
      builder = new MotorCycleBuilder();
      shop.Construct(builder);
      builder.Vehicle.Show();
 
      // Wait for user
      Console.ReadKey();
    }
  }
 
  /// <summary>
  /// The 'Director' class
  /// </summary>
  class Shop
  {
    // Builder uses a complex series of steps
    public void Construct(VehicleBuilder vehicleBuilder)
    {
      vehicleBuilder.BuildFrame();
      vehicleBuilder.BuildEngine();
      vehicleBuilder.BuildWheels();
      vehicleBuilder.BuildDoors();
    }
  }
 
  /// <summary>
  /// The 'Builder' abstract class
  /// </summary>
  abstract class VehicleBuilder
  {
    protected Vehicle vehicle;
 
    // Gets vehicle instance
    public Vehicle Vehicle
    {
      get { return vehicle; }
    }
 
    // Abstract build methods
    public abstract void BuildFrame();
    public abstract void BuildEngine();
    public abstract void BuildWheels();
    public abstract void BuildDoors();
  }
 
  /// <summary>
  /// The 'ConcreteBuilder1' class
  /// </summary>
  class MotorCycleBuilder : VehicleBuilder
  {
    public MotorCycleBuilder()
    {
      vehicle = new Vehicle("MotorCycle");
    }
 
    public override void BuildFrame()
    {
      vehicle["frame"] = "MotorCycle Frame";
    }
 
    public override void BuildEngine()
    {
      vehicle["engine"] = "500 cc";
    }
 
    public override void BuildWheels()
    {
      vehicle["wheels"] = "2";
    }
 
    public override void BuildDoors()
    {
      vehicle["doors"] = "0";
    }
  }
 
 
  /// <summary>
  /// The 'ConcreteBuilder2' class
  /// </summary>
  class CarBuilder : VehicleBuilder
  {
    public CarBuilder()
    {
      vehicle = new Vehicle("Car");
    }
 
    public override void BuildFrame()
    {
      vehicle["frame"] = "Car Frame";
    }
 
    public override void BuildEngine()
    {
      vehicle["engine"] = "2500 cc";
    }
 
    public override void BuildWheels()
    {
      vehicle["wheels"] = "4";
    }
 
    public override void BuildDoors()
    {
      vehicle["doors"] = "4";
    }
  }
 
  /// <summary>
  /// The 'ConcreteBuilder3' class
  /// </summary>
  class ScooterBuilder : VehicleBuilder
  {
    public ScooterBuilder()
    {
      vehicle = new Vehicle("Scooter");
    }
 
    public override void BuildFrame()
    {
      vehicle["frame"] = "Scooter Frame";
    }
 
    public override void BuildEngine()
    {
      vehicle["engine"] = "50 cc";
    }
 
    public override void BuildWheels()
    {
      vehicle["wheels"] = "2";
    }
 
    public override void BuildDoors()
    {
      vehicle["doors"] = "0";
    }
  }
 
  /// <summary>
  /// The 'Product' class
  /// </summary>
  class Vehicle
  {
    private string _vehicleType;
    private Dictionary<string,string> _parts = 
      new Dictionary<string,string>();
 
    // Constructor
    public Vehicle(string vehicleType)
    {
      this._vehicleType = vehicleType;
    }
 
    // Indexer
    public string this[string key]
    {
      get { return _parts[key]; }
      set { _parts[key] = value; }
    }
 
    public void Show()
    {
      Console.WriteLine("\n---------------------------");
      Console.WriteLine("Vehicle Type: {0}", _vehicleType);
      Console.WriteLine(" Frame : {0}", _parts["frame"]);
      Console.WriteLine(" Engine : {0}", _parts["engine"]);
      Console.WriteLine(" #Wheels: {0}", _parts["wheels"]);
      Console.WriteLine(" #Doors : {0}", _parts["doors"]);
    }
  }
}

산출


차량 종류 : 스쿠터 프레임 : 스쿠터 프레임
엔진 : 없음
# 바퀴 : 2
#Doors : 0


차량 유형 : 자동차
프레임 : 자동차 프레임
엔진 : 2500 cc
# 바퀴 : 4
#Doors : 4


차량 유형 : MotorCycle
프레임 : 모터 사이클 프레임
엔진 : 500cc
# 바퀴 : 2
#Doors : 0

프로토 타입 패턴

프로토 타입 인스턴스를 사용하여 만들 개체의 종류를 지정하고이 프로토 타입을 복사하여 새 개체를 만듭니다.

이 예제에서는 동일한 유형의 기존 사용자 정의 색상을 복사하여 새 Color 객체를 만드는 프로토 타입 패턴을 보여줍니다.

using System;
using System.Collections.Generic;
 
namespace GangOfFour.Prototype
{
  /// <summary>
  /// MainApp startup class for Real-World 
  /// Prototype Design Pattern.
  /// </summary>
  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    static void Main()
    {
      ColorManager colormanager = new ColorManager();
 
      // Initialize with standard colors
      colormanager["red"] = new Color(255, 0, 0);
      colormanager["green"] = new Color(0, 255, 0);
      colormanager["blue"] = new Color(0, 0, 255);
 
      // User adds personalized colors
      colormanager["angry"] = new Color(255, 54, 0);
      colormanager["peace"] = new Color(128, 211, 128);
      colormanager["flame"] = new Color(211, 34, 20);
 
      // User clones selected colors
      Color color1 = colormanager["red"].Clone() as Color;
      Color color2 = colormanager["peace"].Clone() as Color;
      Color color3 = colormanager["flame"].Clone() as Color;
 
      // Wait for user
      Console.ReadKey();
    }
  }
 
  /// <summary>
  /// The 'Prototype' abstract class
  /// </summary>
  abstract class ColorPrototype
  {
    public abstract ColorPrototype Clone();
  }
 
  /// <summary>
  /// The 'ConcretePrototype' class
  /// </summary>
  class Color : ColorPrototype
  {
    private int _red;
    private int _green;
    private int _blue;
 
    // Constructor
    public Color(int red, int green, int blue)
    {
      this._red = red;
      this._green = green;
      this._blue = blue;
    }
 
    // Create a shallow copy
    public override ColorPrototype Clone()
    {
      Console.WriteLine(
        "Cloning color RGB: {0,3},{1,3},{2,3}",
        _red, _green, _blue);
 
      return this.MemberwiseClone() as ColorPrototype;
    }
  }
 
  /// <summary>
  /// Prototype manager
  /// </summary>
  class ColorManager
  {
    private Dictionary<string, ColorPrototype> _colors =
      new Dictionary<string, ColorPrototype>();
 
    // Indexer
    public ColorPrototype this[string key]
    {
      get { return _colors[key]; }
      set { _colors.Add(key, value); }
    }
  }
}

산출:

클론 색상 RGB : 255, 0, 0

클론 색상 RGB : 128,211,128

클론 색상 RGB : 211, 34, 20

추상 공장 패턴

구체적인 클래스를 지정하지 않고 관련 객체 또는 종속 객체의 패밀리를 작성하기위한 인터페이스를 제공합니다.

이 예제에서는 서로 다른 팩토리를 사용하는 컴퓨터 게임을위한 서로 다른 동물 세계를 만드는 방법을 보여줍니다. 대륙 공장에서 만든 동물은 다르지만 동물 간의 상호 작용은 동일합니다.

using System;
 
namespace GangOfFour.AbstractFactory
{
  /// <summary>
  /// MainApp startup class for Real-World
  /// Abstract Factory Design Pattern.
  /// </summary>
  class MainApp
  {
    /// <summary>
    /// Entry point into console application.
    /// </summary>
    public static void Main()
    {
      // Create and run the African animal world
      ContinentFactory africa = new AfricaFactory();
      AnimalWorld world = new AnimalWorld(africa);
      world.RunFoodChain();
 
      // Create and run the American animal world
      ContinentFactory america = new AmericaFactory();
      world = new AnimalWorld(america);
      world.RunFoodChain();
 
      // Wait for user input
      Console.ReadKey();
    }
  }
 
 
  /// <summary>
  /// The 'AbstractFactory' abstract class
  /// </summary>
  abstract class ContinentFactory
  {
    public abstract Herbivore CreateHerbivore();
    public abstract Carnivore CreateCarnivore();
  }
 
  /// <summary>
  /// The 'ConcreteFactory1' class
  /// </summary>
  class AfricaFactory : ContinentFactory
  {
    public override Herbivore CreateHerbivore()
    {
      return new Wildebeest();
    }
    public override Carnivore CreateCarnivore()
    {
      return new Lion();
    }
  }
 
  /// <summary>
  /// The 'ConcreteFactory2' class
  /// </summary>
  class AmericaFactory : ContinentFactory
  {
    public override Herbivore CreateHerbivore()
    {
      return new Bison();
    }
    public override Carnivore CreateCarnivore()
    {
      return new Wolf();
    }
  }
 
  /// <summary>
  /// The 'AbstractProductA' abstract class
  /// </summary>
  abstract class Herbivore
  {
  }
 
  /// <summary>
  /// The 'AbstractProductB' abstract class
  /// </summary>
  abstract class Carnivore
  {
    public abstract void Eat(Herbivore h);
  }
 
  /// <summary>
  /// The 'ProductA1' class
  /// </summary>
  class Wildebeest : Herbivore
  {
  }
 
  /// <summary>
  /// The 'ProductB1' class
  /// </summary>
  class Lion : Carnivore
  {
    public override void Eat(Herbivore h)
    {
      // Eat Wildebeest
      Console.WriteLine(this.GetType().Name +
        " eats " + h.GetType().Name);
    }
  }
 
  /// <summary>
  /// The 'ProductA2' class
  /// </summary>
  class Bison : Herbivore
  {
  }
 
  /// <summary>
  /// The 'ProductB2' class
  /// </summary>
  class Wolf : Carnivore
  {
    public override void Eat(Herbivore h)
    {
      // Eat Bison
      Console.WriteLine(this.GetType().Name +
        " eats " + h.GetType().Name);
    }
  }
 
  /// <summary>
  /// The 'Client' class 
  /// </summary>
  class AnimalWorld
  {
    private Herbivore _herbivore;
    private Carnivore _carnivore;
 
    // Constructor
    public AnimalWorld(ContinentFactory factory)
    {
      _carnivore = factory.CreateCarnivore();
      _herbivore = factory.CreateHerbivore();
    }
 
    public void RunFoodChain()
    {
      _carnivore.Eat(_herbivore);
    }
  }
}

산출:

사자가 Wildebeest를 먹는다.

늑대는 들소를 먹는다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow