전략 패턴(StrategyPattern)

최용국·2020년 2월 24일
0

디자인패턴

목록 보기
2/6

20-0224 StrategyPattern

비용이 적게 드는 방향으로 빠르게 개발하게 되면 효율적으로 코드를 짜기 어렵다

내 개발 비용과 컴퓨터의 비용은 반비례하는 것 같다. 알고리즘이 그렇다.

어떠한 목록(list)에서 연산을 하는 함수를 만든다고 가정할 때 내 개발 비용이 적게 들기 위해 최악의 알고리즘으로 짜는 대신 그 알고리즘을 일반화하여 확장에 열어두고 넘어갈 때 자주 쓰는 패턴이다.

예제는 알고리즘을 다룬 것은 아니고 출력하는 함수가 있고 목록(list)의 전략(Strategy)에 따라 정방향, 역방향으로 출력할 수 있게 일반화 한 것이다.
List를 상속받은 MyList라는 Collection이 있고 MyList는 Read() 함수를 통해 아이템 (Generic)을 읽어온다. 읽어올 때 IReadTypes[]에 사전 정의되어있는 ForWardRead, BackWardRead 중 가장 처음 생성된 ForWardRead 방식이 CurrentReadType이다. Read를 하게 되면 ForWardRead 방식으로 읽어온다. Change 함수를 호출하게 되면 CurrentReadType이 ForWardRead → BackWardRead로 변경되고 Read()를 호출하면 BackWardRead 방식으로 읽어온다.

그리고 마지막으로는 해당 Collection이 수정되는 것이 아니라는 것을 보여준다.

interface IRead

public interface IRead<T>
{
    IEnumerable<T> Read(List<T> list);
}

class ForwardRead, BackwardRead

public class BackwardRead<T> : IRead<T> where T : class
{
    public IEnumerable<T> Read(List<T> list)
    {
        for (int i = list.Count - 1; i >= 0; i--)
        {
            yield return list[i];
        }
    }
}

public class ForwardRead<T> : IRead<T> where T : class
{
    public IEnumerable<T> Read(List<T> list)
    {
        for (int i = 0; i < list.Count; i++)
        {
            yield return list[i];
        }
    }
}

class Person

public class Person
{
    public string Name
    {
        get; set;
    }

    public int Age
    {
        get; set;
    }

    public Person(string name, int age)
    {
        this.Name = name;
        this.Age = age;
    }

    public override string ToString()
    {
        return $"이름: {this.Name} 나이: {this.Age}";
    }
}

class MyList

public class MyList<T> : IList<T> where T: class
{
    public List<T> Collection { get; private set; }
    public IRead<T>[] ReadTypes { get; private set; }
    public IRead<T> CurrentReadType { get; private set; }
    private int CurrentReadTypeIndex { get; set; } = 0;
    public MyList()
    {
        this.ReadTypes = new IRead<T>[2] { new ForwardRead<T>(), new BackwardRead<T>() };
        this.CurrentReadType = ReadTypes[CurrentReadTypeIndex];
        this.Collection = new List<T>();
    }

    public void ChangeType()
    {
        CurrentReadTypeIndex++;
        if (CurrentReadTypeIndex == ReadTypes.Length)
            CurrentReadTypeIndex = 0;
        this.CurrentReadType = ReadTypes[CurrentReadTypeIndex];
    }

    public IEnumerable<T> Read() => this.CurrentReadType.Read(this.Collection);

    public T this[int index] { get => Collection[index]; set => Collection[index] = value; }

    public int Count => Collection.Count;

    public bool IsReadOnly => true;

    public void Add(T item) => Collection.Add(item);

    public void Clear() => Collection.Clear();

    public bool Contains(T item) => Collection.Contains(item);

    public void CopyTo(T[] array, int arrayIndex) => Collection.CopyTo(array, arrayIndex);

    public IEnumerator<T> GetEnumerator() => Collection.GetEnumerator();

    public int IndexOf(T item) => Collection.IndexOf(item);

    public void Insert(int index, T item) => Collection.Insert(index, item);

    public bool Remove(T item) => Collection.Remove(item);

    public void RemoveAt(int index) => Collection.RemoveAt(index);

    IEnumerator IEnumerable.GetEnumerator() => Collection.GetEnumerator();

}

Program

class Program
{
    static void Main(string[] args)
    {
        MyList<Person> people = new MyList<Person>()
        {
            new Person("최용국", 28),
            new Person("이은혜", 31),
            new Person("이정선", 29),
            new Person("안광필", 35)
        };
        
        foreach (var person in people.Read())
        {
            Console.WriteLine(person);
        }
        Console.WriteLine("=================================");
        people.ChangeType();
        foreach (var person in people.Read())
        {
            Console.WriteLine(person);
        }
        Console.WriteLine("=================================");
        foreach (var person in people)
        {
            Console.WriteLine(person);
        }



        Console.ReadLine();

    }
}

결과

profile
코딩합시다.

0개의 댓글