<file_sep>namespace mediator
{
    public class Heater : IColleague
    {
        public IMachineMediator Mediator { get; set; }

        public void On(int temp)
        {
            System.Console.WriteLine("Heater is on...");

            if (Mediator.CheckTemperature(temp))
            {
                System.Console.WriteLine($"Temperature is set to {temp}");
            }

            Mediator.Off();
        }
        public void Off()
        {
            System.Console.WriteLine("Heater is off...");

            Mediator.Wash();
        }
    }
}<file_sep>using System;

namespace command
{
    public class Email
    {
        public void SendEmail() => Console.WriteLine("Sending email.......");
    }
}<file_sep>using System;

namespace command
{
    public class FileIO
    {
        public void Execute() => Console.WriteLine("Executing File IO operations...");
    }
}<file_sep>using System.Linq.Expressions;

namespace interpreter
{
    public class Add : IExpression
    {
        private IExpression leftExpression;
        private IExpression rightExpression;

        public int Interpret() => leftExpression.Interpret() + rightExpression.Interpret();
    }
}<file_sep>namespace command
{
    public class FileIOJob : IJob
    {
        private FileIO _fileIO;

        public void Run()
        {
            if (_fileIO != null)
            {
                _fileIO.Execute();
            }
        }

        public void FileIO(FileIO fileIo) => _fileIO = fileIo;
    }
}<file_sep>namespace mediator
{
    public class SoilRemoval
    {
        public void Low() => System.Console.WriteLine("Setting Soil Removal to low");
        public void Medium() => System.Console.WriteLine("Setting Soil Removal to medium");
        public void High() => System.Console.WriteLine("Setting Soil Removal to high");
    }
}<file_sep>using System;

namespace mediator
{
    public class CottonMediator : IMachineMediator
    {
        private const int DrumSpeed = 700;
        private const int Temperature = 40;
        private Machine machine { get; set; }
        private Heater heater { get; set; }
        private Motor motor { get; set; }
        private Sensor sensor { get; set; }
        private SoilRemoval soilRemoval { get; set; }
        private Valve valve { get; set; }

        public CottonMediator(Machine machine, Heater heater, Motor motor, Sensor sensor,
            SoilRemoval soilRemoval, Valve valve)
        {
            Console.WriteLine($"............... Setting up for COTTON program ...............");
            this.machine = machine;
            this.heater = heater;
            this.motor = motor;
            this.sensor = sensor;
            this.soilRemoval = soilRemoval;
            this.valve = valve;
        }

        public void Start() => machine.Start();

        public void Wash()
        {
            motor.StartMotor();
            motor.RotateDrum(DrumSpeed);

            Console.WriteLine("Adding detergent");
            soilRemoval.Low();
            Console.WriteLine("Adding softener");
        }

        public void Open() => valve.Open();

        public void Closed() => valve.Closed();

        public void On() => heater.On(Temperature);

        public void Off() => heater.Off();

        public bool CheckTemperature(int temp) => sensor.CheckTemperature(temp);
    }
}<file_sep># Behavioural Design Patterns (part one)

This repo contains my solutions to a series of design pattern questions.

Patterns implemented:
- Chain
- Command
- Interpreter
- Iterator
- Mediator


<file_sep>namespace mediator
{
    public class Sensor
    {
        public bool CheckTemperature(int temp)
        {
            System.Console.WriteLine($"Temperature reached {temp} C");
            return true;
        }
    }
}<file_sep>using System;

namespace mediator
{
    public class Valve : IColleague
    {
        public IMachineMediator Mediator { get; set; }
        public void Open()
        {
            Console.WriteLine("Valve is opened...");
            Console.WriteLine("Filling water...");
            Mediator.Closed();
        }
        public void Closed()
        {
            Console.WriteLine("Valve is closed...");
            Mediator.On();
        }
    }
}<file_sep>using System;

namespace command
{
    public class Logging
    {
        public void Log() => Console.WriteLine("Logging...");
    }
}<file_sep>﻿using System;
using System.Collections.Generic;

namespace worksheet_eight_behavioural_design_patterns
{
    public static class TestChainOfResponsibility
    {
        public static void Main(string[] args)
        {
            IHandler textHandler = new TextFileHandler("Text Handler");
            IHandler docHandler = new DocFileHandler("Doc Handler");
            IHandler excelHandler = new ExcelFileHandler("Excel Handler");
            IHandler audioHandler = new AudioFileHandler("Audio Handler");
            IHandler videoHandler = new VideoFileHandler("Video Handler");
            IHandler imageHandler = new ImageFileHandler("Image Handler");

            textHandler.Handler = docHandler;
            docHandler.Handler = excelHandler;
            excelHandler.Handler = audioHandler;
            audioHandler.Handler = videoHandler;
            videoHandler.Handler = imageHandler;

            var file = new File("Abc.mp3", "audio", "C:");
            textHandler.Process(file);

            Console.WriteLine("--------------------");

            file = new File("Abc.jpg", "video", "C:");
            textHandler.Process(file);

            Console.WriteLine("--------------------");

            file = new File("Abc.doc", "doc", "C:");
            textHandler.Process(file);

            Console.WriteLine("--------------------");

            file = new File("Abc.bat", "bat", "C:");
            textHandler.Process(file);
        }
    }
}<file_sep>using System;

namespace worksheet_eight_behavioural_design_patterns
{
    public class ExcelFileHandler : IHandler
    {
        public ExcelFileHandler(string textHandler)
        {
            HandlerName = textHandler;
        }

        public IHandler Handler { get; set; }
        public string HandlerName { get; }
        public void Process(object file)
        {
            File fileObj = (File)file;

            if (fileObj.Type.Equals("excel"))
            {
                Console.WriteLine($"Process and saving excel file... by {HandlerName}");
            }
            else
            {
                if (Handler != null)
                {
                    Console.WriteLine($"{HandlerName} forwards request to {Handler.HandlerName}");
                    Handler.Process(file);
                }
                else
                {
                    Console.WriteLine("File not supported");
                }
            }
        }
    }
}<file_sep>﻿using System;

namespace command
{
    public static class TestCommandPattern
    {
        public static void Main(string[] args)
        {
            const int numberOfThreads = 10;
            const int numberOfJobs = 5;

            var pool = new ThreadPool<IJob>(numberOfThreads);

            var emailJob = new EmailJob();
            var smsJob = new SmsJob();
            var fileIOJob = new FileIOJob();
            var logJob = new LoggingJob();

            for (var i = 0; i < numberOfJobs; i++)
            {
                emailJob.Email(new Email());
                smsJob.Sms(new Sms());
                fileIOJob.FileIO(new FileIO());
                logJob.Logging = new Logging();
                pool.AddJob(emailJob);
                pool.AddJob(smsJob);
                pool.AddJob(fileIOJob);
                pool.AddJob(logJob);
            }

            pool.ShutdownPool();
        }
    }
}<file_sep>﻿using System;

namespace iterator
{
    public static class TestIteratorPattern
    {
        public static void Main(string[] args)
        {
            var storage = new ShapeStorage<Shape>();
            storage.AddShape("Polygon");
            storage.AddShape("Hexagon");
            storage.AddShape("Circle");
            storage.AddShape("Rectangle");
            storage.AddShape("Square");

            var iterator = new ShapeIterator<ShapeStorage<Shape>>(storage);

            while (iterator.MoveNext())
            {
                Console.WriteLine(iterator.Current);
            }

            Console.WriteLine("Removing items while iterating...");
            iterator.Reset(); // reposition the iterator

            while (iterator.MoveNext())
            {
                Console.WriteLine(iterator.Current);
                iterator.Dispose();
            }
        }
    }
}<file_sep>using System.Collections;
using System.Collections.Generic;

namespace iterator
{
    public class ShapeIterator<TShape> : IEnumerator<TShape>
    {
        private TShape _collection;
        private int pos = -1;

        public ShapeIterator(TShape collection)
        {
            Current = collection;
            _collection = collection;
        }

        public bool MoveNext()
        {
            pos++;
            return false; // todo
        }

        public void Reset()
        {
            pos = -1;
        }

        public TShape Current { get; }

        object? IEnumerator.Current => Current;

        public void Dispose()
        {
            throw new System.NotImplementedException();
        }
    }
}<file_sep>using System;

namespace mediator
{
    public class Button : IColleague
    {
        public IMachineMediator Mediator { get; set; }

        public void Press()
        {
            Console.WriteLine("Button pressed.");
            Mediator.Start();
        }
    }
}<file_sep>using System;

namespace worksheet_eight_behavioural_design_patterns
{
    public class DocFileHandler : IHandler
    {
        public DocFileHandler(string textHandler)
        {
            HandlerName = textHandler;
        }

        public IHandler Handler { get; set; }
        public string HandlerName { get; }
        public void Process(object file)
        {
            File fileObj = (File)file;

            if (fileObj.Type.Equals("doc"))
            {
                Console.WriteLine($"Process and saving doc file... by {HandlerName}");
            }
            else
            {
                if (Handler != null)
                {
                    Console.WriteLine($"{HandlerName} forwards request to {Handler.HandlerName}");
                    Handler.Process(file);
                }
                else
                {
                    Console.WriteLine("File not supported");
                }
            }
        }
    }
}<file_sep>﻿using System;
using System.Collections.Generic;

namespace interpreter
{
    public static class TestInterpreterPattern
    {
        public static void Main(string[] args)
        {
            var tokenString = "7 3 - 2 1 + *";
            var stack = new Stack<IExpression>();
            var tokenArray = tokenString.Split(" ");
            foreach (var s in tokenArray)
            {
                if (ExpressionUtils.IsOperator(s))
                {
                    var rightExpression = stack.Pop();
                    var leftExpression = stack.Pop();
                    var op = ExpressionUtils.GetOperator(s, leftExpression, rightExpression);
                    stack.Push(new Number(op.Interpret()));
                }
                else
                {
                    stack.Push(new Number(Int32.Parse(s)));
                }
            }

            Console.WriteLine($"( {tokenString} ) {stack.Pop().Interpret()}");
        }
    }
}<file_sep>using System;

namespace iterator
{
    public class ShapeStorage<T> where T : Shape, new()
    {
        private const int NumberOfShapes = 5;
        private readonly T[] _shapes = new T[NumberOfShapes];
        private int _index = 0;

        public void AddShape(string name) =>
            _shapes[_index++] = new T {Id = _index, Name = name};

        public T[] GetShapes()
        {
            T[] copy = new T[NumberOfShapes];

            for (int i = 0; i < NumberOfShapes; i++)
            {
                if (_shapes[i] != null)
                {
                    copy[i] = _shapes[i];
                }
            }

            //Array.Copy(_shapes, copy, NumberOfShapes);

            return copy;
        }
        // Additional methods?

        public T this[int i]
        {
            get => _shapes[i];
            set => _shapes[i] = value;
        }
        // Indexer?
    }
}<file_sep>namespace command
{
    public class LoggingJob : IJob
    {
        public Logging Logging { set; get; }

        public void Run()
        {
            if (Logging != null)
            {
                Logging.Log();
            }
        }
    }
}<file_sep>﻿using System;

namespace mediator
{
    public static class TestMediator
    {
        public static void Main(string[] args)
        {
            var sensor = new Sensor();
            var soilRemoval = new SoilRemoval();
            var motor = new Motor();
            var machine = new Machine();
            var heater = new Heater();
            var valve = new Valve();
            var button = new Button();

            IMachineMediator mediator = new CottonMediator(machine, heater, motor, sensor, soilRemoval, valve);

            button.Mediator = mediator;
            machine.Mediator = mediator;
            heater.Mediator = mediator;
            valve.Mediator = mediator;

            button.Press();

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

            mediator = new DenimMediator(machine, heater, motor, sensor, soilRemoval, valve);
            button.Mediator = mediator;
            machine.Mediator = mediator;
            heater.Mediator = mediator;
            valve.Mediator = mediator;

            button.Press();
        }
    }
}<file_sep>using System;

namespace mediator
{
    public class Motor
    {
        public void StartMotor() => Console.WriteLine("Start motor...");
        public void RotateDrum(int rpm) => Console.WriteLine($"Rotating drum at {rpm} rpm.");
    }
}<file_sep>using System;

namespace command
{
    public class Sms
    {
        public void SendSms() => Console.WriteLine("Sending SMS...");
    }
}<file_sep>namespace worksheet_eight_behavioural_design_patterns
{
    public interface IHandler
    {
        IHandler Handler { get; set; }
        string HandlerName { get; }
        void Process(object file);
    }
}<file_sep>namespace command
{
    public class SmsJob : IJob
    {
        private Sms _sms;

        public void Run()
        {
            if (_sms != null)
            {
                _sms.SendSms();
            }
        }

        public void Sms(Sms sms) => _sms = sms;
    }
}<file_sep>namespace interpreter
{
    public class Product : IExpression
    {
        private IExpression leftExpression;
        private IExpression rightExpression;

        public int Interpret() => leftExpression.Interpret() * rightExpression.Interpret();
    }
}<file_sep>using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;

namespace command
{
    public class ThreadPool<T> where T: IJob
    {
        private static BlockingCollection<T> jobQueue = new BlockingCollection<T>();
        private Thread[] jobThreads;
        private static bool shutdown;

        public ThreadPool(int numberOfThreads)
        {
            jobThreads = new Thread[numberOfThreads];

            for (var i = 0; i < numberOfThreads; i++)
            {
                Worker worker = new Worker();
                jobThreads[i] = new Thread(worker.Run);
                jobThreads[i].Name = $"Job ID: {i}";
                //throw new System.NotImplementedException();
            }
        }

        public void AddJob(T job)
        {
            jobQueue.Add(job);
        }

        public void ShutdownPool()
        {
            const int sleepTime = 1000;

            while (jobQueue.Count > 0)
            {
                try
                {
                    jobThreads.ToList().ForEach(n => n.Start());
                    Thread.Sleep(sleepTime);
                    //jobThreads[0].Start();
                    //Thread.Sleep(sleepTime);
                    // some code here?
                }
                catch (ThreadInterruptedException ex)
                {
                    Console.WriteLine(ex.StackTrace);
                }
            }

            shutdown = true;
            foreach (var workerThread in jobThreads)
            {
                workerThread.Interrupt();
            }
        }

        private class Worker /*(string name)*/ : ThreadLocal<IJob>
        {
            //string _name;

            //Worker(string name)
            //{
            //    _name = name;
            //}
            public void Run()
            {
                while (!shutdown)
                {
                    try
                    {
                        var r = jobQueue.Take();
                        r.Run();
                    }
                    catch (ThreadInterruptedException ex)
                    {
                        Console.WriteLine(ex.StackTrace); //?
                    }
                }
            }
        }
    }
}<file_sep>namespace interpreter
{
    public sealed class ExpressionUtils
    {
        public static bool IsOperator(string s)
        {
            throw new System.NotImplementedException();
        }

        public static IExpression GetOperator(string s, IExpression left, IExpression right)
        {
            throw new System.NotImplementedException();
        }
    }
}<file_sep>namespace command
{
    public class EmailJob : IJob
    {
        private Email _email;

        public void Run()
        {
            if (_email != null)
            {
                _email.SendEmail();
            }
        }

        public void Email(Email email) => _email = email;
    }
}<file_sep>namespace interpreter
{
    public class Number : IExpression
    {
        internal Number(int n)
        {
            throw new System.NotImplementedException();
        }


        public int Interpret()
        {
            throw new System.NotImplementedException();
        }
    }
}<file_sep>namespace mediator
{
    public interface IMachineMediator
    {
        void Start();
        void Wash();
        void Open();
        void Closed();
        void On();
        void Off();
        bool CheckTemperature(int temp);
    }
}<file_sep>namespace mediator
{
    public interface IColleague
    {
        IMachineMediator Mediator { get; set; }
    }
}<file_sep>namespace worksheet_eight_behavioural_design_patterns
{
    /// <summary>
    /// This is just a dummy class rather than using a real class - a mock.
    /// </summary>
    public class File
    {
        public string FileName { get; }
        public string Type { get; }
        public string Location { get; }

        public File(string fileName, string type, string location)
        {
            FileName = fileName;
            Type = type;
            Location = location;
        }  
    }
}<file_sep>namespace mediator
{
    public class Machine : IColleague
    {
        public IMachineMediator Mediator { get; set; }

        public void Start() => Wash();
        public void Wash() => Mediator.Open();
    }
}