1. 템플릿 메서드 패턴


부모 클래스에서 템플릿(코드의 틀)을 마련하고

서브 클래스에서 부모 클래스의 메서드를 오버라이드해서 구현하는 방식


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
 
namespace TextFileProcessor
{
    public abstract class TextProcessor
    {
        public static void Run<T>(string fileName) where T : TextProcessor, new()
        {
            var self = new T();
            self.Process(fileName);
        }
 
        private void Process(string fileName)
        {
            Initialize(fileName);
            using (var sr = new StreamReader(fileName))
            {
                while (!sr.EndOfStream)
                {
                    string line = sr.ReadLine();
                    Execute(line);
                }
            }
            Terminate();
        }
 
        protected virtual void Initialize(string fName) { }
        protected virtual void Execute(string line) { }
        protected virtual void Terminate() { }
    }
}
cs


where T : TextProcessor는 형 T가 TextProcessor거나 이를 상속한 서브클래스만 허용한다는 의미,

뒤의 new()는 형T가 인수를 가지지 않는 생성자로 인스턴스를 생성할 수 있다는 것을 나타냄



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TextFileProcessor;
 
namespace LineCounter
{
    class Program
    {
        static void Main(string[] args)
        {
            TextProcessor.Run<LineCounterProcessor>("apple.txt");
        }
    }
 
    class LineCounterProcessor : TextProcessor
    {
        private int _count;
 
        protected override void Initialize(string fName)
        {
            _count = 0;
        }
 
        protected override void Execute(string line)
        {
            _count++;
        }
 
        protected override void Terminate()
        {
            Console.WriteLine("{0}줄", _count);
        }
    }
}
 
cs





2. 전략 패턴


동적으로 알고리즘을 교체할 수 있는 패턴


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace Converter
{
    public abstract class ConverterBase
    {
        public abstract bool IsMyUnit(string name);
        protected abstract double Ratio { get; }
        public abstract string UnitName { get; }
 
        public double FromMeter(double meter)
        {
            return meter / Ratio;
        }
 
        public double ToMeter(double feet)
        {
            return feet * Ratio;
        }
    }
 
    public class MeterConverter : ConverterBase
    {
        public override bool IsMyUnit(string name)
        {
            return name.ToLower() == "meter" || name == UnitName;
        }
        protected override double Ratio { get { return 1; } }
        public override string UnitName { get { return "미터"; } }
    }
 
    public class FeetConverter : ConverterBase
    {
        public override bool IsMyUnit(string name)
        {
            return name.ToLower() == "feet" || name == UnitName;
        }
        protected override double Ratio { get { return 0.3048; } }
        public override string UnitName { get { return "피트"; } }
    }
 
    public class InchConverter : ConverterBase
    {
        public override bool IsMyUnit(string name)
        {
            return name.ToLower() == "inch" || name == UnitName;
        }
        protected override double Ratio { get { return 0.0254; } }
        public override string UnitName { get { return "인치"; } }
    }
 
    public class YardConverter : ConverterBase
    {
        public override bool IsMyUnit(string name)
        {
            return name.ToLower() == "yard" || name == UnitName;
        }
        protected override double Ratio { get { return 0.9144; } }
        public override string UnitName { get { return "야드"; } }
    }
 
    public class DistanceConverter
    {
        public ConverterBase From { get; private set; }
        public ConverterBase To { get; private set; }
 
        public DistanceConverter(ConverterBase from, ConverterBase to)
        {
            From = from;
            To = to;
        }
 
        public double Convert(double value)
        {
            var meter = From.ToMeter(value);
            return To.FromMeter(meter);
        }
    }
 
    public static class DitanceFactory
    {
        private static ConverterBase[] _converters = new ConverterBase[]
        {
            new MeterConverter(),
            new FeetConverter(),
            new YardConverter(),
            new InchConverter()
        };
 
        public static ConverterBase GetInstance(string name)
        {
            return _converters.FirstOrDefault(x => x.IsMyUnit(name));
        }
    }
}
cs


ConverterBase라는 부모 클래스가 있고 이를 상속받아 구현한 Meter, Feet, Inch, Yard 4개의 클래스가 있음.

단위 변환해주는 DistanceConveter 클래스가 있고, 이를 묶어서 찾기 쉽게한 DistanceFactory 클래스가 있음.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace Converter
{
    class Program
    {
        static void Main(string[] args)
        {
            var from = GetConverter("변환할 단위를 입력하세요.");
            var to = GetConverter("변환 결과 단위를 입력하세요.");
            var distance = GetDistance(from);
 
            var converter = new DistanceConverter(from, to);
            var result = converter.Convert(distance);
            Console.WriteLine($"{distance}{from.UnitName}는 {result:0.000}{to.UnitName}입니다. \n");
        }
 
        static double GetDistance(ConverterBase from)
        {
            double? value = null;
            do
            {
                Console.Write($"변환하려는 거리(단위:{from.UnitName})를 입력하세요 => ");
                var line = Console.ReadLine();
                double temp;
                value = double.TryParse(line, out temp) ? (double?)temp : null;
            } while (value == null);
            return value.Value;
        }
 
        static ConverterBase GetConverter(string msg)
        {
            ConverterBase converter = null;
            do
            {
                Console.Write(msg + " => ");
                var unit = Console.ReadLine();
                converter = DitanceFactory.GetInstance(unit);
            } while (converter == null);
            return converter;
        }
    }
}
cs



Posted by misty_
,