Мост или завод и как - PullRequest
0 голосов
/ 16 июня 2010

Я пытаюсь выучить шаблоны, и у меня есть работа, которая требует шаблона, я просто знаю, но не могу понять.Я знаю, что тип фильтра - это то, что можно абстрагировать и, возможно, соединить.Я не ищу переписать код просто предложения.Я не ищу кого-то, чтобы делать мою работу.Я хотел бы знать, как шаблоны могут быть применены к этому примеру.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
using System.Xml;
using System.Text.RegularExpressions;

namespace CopyTool
{
    class CopyJob
    {
        public enum FilterType
        { TextFilter, RegExFilter, NoFilter }
        public FilterType JobFilterType { get; set; }

        private string _jobName;
        public string JobName { get { return _jobName; } set { _jobName = value; } }

        private int currentIndex;
        public int CurrentIndex { get { return currentIndex; } }

        private DataSet ds;

        public int MaxJobs { get { return ds.Tables["Job"].Rows.Count; } }

        private string _filter;
        public string Filter { get { return _filter; } set { _filter = value; } }

        private string _fromFolder;
        public string FromFolder
        {
            get { return _fromFolder; }
            set
            {
                if (Directory.Exists(value))
                { _fromFolder = value; }
                else
                { throw new DirectoryNotFoundException(String.Format("Folder not found: {0}", value)); }
            }
        }

        private List<string> _toFolders;
        public List<string> ToFolders { get { return _toFolders; } }

        public CopyJob()
        {
            Initialize();
        }

        private void Initialize()
        {
            if (ds == null)
            { ds = new DataSet(); }
            ds.ReadXml(Properties.Settings.Default.ConfigLocation);
            LoadValues(0);
        }

        public void Execute()
        {
            ExecuteJob(FromFolder, _toFolders, Filter, JobFilterType);
        }

        public void ExecuteAll()
        {
            string OrigPath;
            List<string> DestPaths;
            string FilterText;
            FilterType FilterWay;
            foreach (DataRow rw in ds.Tables["Job"].Rows)
            {
                OrigPath = rw["FromFolder"].ToString();
                FilterText = rw["FilterText"].ToString();
                switch (rw["FilterType"].ToString())
                {
                    case "TextFilter":
                        FilterWay = FilterType.TextFilter;
                        break;
                    case "RegExFilter":
                        FilterWay = FilterType.RegExFilter;
                        break;
                    default:
                        FilterWay = FilterType.NoFilter;
                        break;
                }
                DestPaths = new List<string>();
                foreach (DataRow crw in rw.GetChildRows("Job_ToFolder"))
                {
                    DestPaths.Add(crw["FolderPath"].ToString());
                }
                ExecuteJob(OrigPath, DestPaths, FilterText, FilterWay);
            }
        }

        private void ExecuteJob(string OrigPath, List<string> DestPaths, string FilterText, FilterType FilterWay)
        {
            FileInfo[] files;
            switch (FilterWay)
            {
                case FilterType.RegExFilter:
                    files = GetFilesByRegEx(new Regex(FilterText), OrigPath);
                    break;
                case FilterType.TextFilter:
                    files = GetFilesByFilter(FilterText, OrigPath);
                    break;
                default:
                    files = new DirectoryInfo(OrigPath).GetFiles();
                    break;
            }
            foreach (string fld in DestPaths)
            {
                CopyFiles(files, fld);
            }
        }

        public void MoveToJob(int RecordNumber)
        {
            Save();
            LoadValues(RecordNumber - 1);
        }

        public void AddToFolder(string folderPath)
        {
            if (Directory.Exists(folderPath))
            { _toFolders.Add(folderPath); }
            else
            { throw new DirectoryNotFoundException(String.Format("Folder not found: {0}", folderPath)); }
        }

        public void DeleteToFolder(int index)
        {
            _toFolders.RemoveAt(index);
        }

        public void Save()
        {
            DataRow rw = ds.Tables["Job"].Rows[currentIndex];
            rw["JobName"] = _jobName;
            rw["FromFolder"] = _fromFolder;
            rw["FilterText"] = _filter;
            switch (JobFilterType)
            {
                case FilterType.RegExFilter:
                    rw["FilterType"] = "RegExFilter";
                    break;
                case FilterType.TextFilter:
                    rw["FilterType"] = "TextFilter";
                    break;
                default:
                    rw["FilterType"] = "NoFilter";
                    break;
            }
            DataRow[] ToFolderRows = ds.Tables["Job"].Rows[currentIndex].GetChildRows("Job_ToFolder");
            for (int i = 0; i <= ToFolderRows.GetUpperBound(0); i++)
            {
                ToFolderRows[i].Delete();
            }
            foreach (string fld in _toFolders)
            {
                DataRow ToFolderRow = ds.Tables["ToFolder"].NewRow();
                ToFolderRow["JobId"] = ds.Tables["Job"].Rows[currentIndex]["JobId"];
                ToFolderRow["Job_Id"] = ds.Tables["Job"].Rows[currentIndex]["Job_Id"];
                ToFolderRow["FolderPath"] = fld;
                ds.Tables["ToFolder"].Rows.Add(ToFolderRow);
            }
        }

        public void Delete()
        {
            ds.Tables["Job"].Rows.RemoveAt(currentIndex);
            LoadValues(currentIndex++);
        }

        public void MoveNext()
        {
            Save();
            currentIndex++;
            LoadValues(currentIndex);
        }

        public void MovePrevious()
        {
            Save();
            currentIndex--;
            LoadValues(currentIndex);
        }

        public void MoveFirst()
        {
            Save();
            LoadValues(0);
        }

        public void MoveLast()
        {
            Save();
            LoadValues(ds.Tables["Job"].Rows.Count - 1);
        }

        public void CreateNew()
        {
            Save();
            int MaxJobId = 0;
            Int32.TryParse(ds.Tables["Job"].Compute("Max(JobId)", "").ToString(), out MaxJobId);
            DataRow rw = ds.Tables["Job"].NewRow();
            rw["JobId"] = MaxJobId + 1;
            ds.Tables["Job"].Rows.Add(rw);
            LoadValues(ds.Tables["Job"].Rows.IndexOf(rw));
        }

        public void Commit()
        {
            Save();
            ds.WriteXml(Properties.Settings.Default.ConfigLocation);
        }

        private void LoadValues(int index)
        {
            if (index > ds.Tables["Job"].Rows.Count - 1)
            { currentIndex = ds.Tables["Job"].Rows.Count - 1; }
            else if (index < 0)
            { currentIndex = 0; }
            else
            { currentIndex = index; }
            DataRow rw = ds.Tables["Job"].Rows[currentIndex];
            _jobName = rw["JobName"].ToString();
            _fromFolder = rw["FromFolder"].ToString();
            _filter = rw["FilterText"].ToString();
            switch (rw["FilterType"].ToString())
            {
                case "TextFilter":
                    JobFilterType = FilterType.TextFilter;
                    break;
                case "RegExFilter":
                    JobFilterType = FilterType.RegExFilter;
                    break;
                default:
                    JobFilterType = FilterType.NoFilter;
                    break;
            }
            if (_toFolders == null)
                _toFolders = new List<string>();
            _toFolders.Clear();
            foreach (DataRow crw in rw.GetChildRows("Job_ToFolder"))
            {
                AddToFolder(crw["FolderPath"].ToString());
            }
        }

        private static FileInfo[] GetFilesByRegEx(Regex rgx, string locPath)
        {
            DirectoryInfo d = new DirectoryInfo(locPath);
            FileInfo[] fullFileList = d.GetFiles();
            List<FileInfo> filteredList = new List<FileInfo>();
            foreach (FileInfo fi in fullFileList)
            {
                if (rgx.IsMatch(fi.Name))
                {
                    filteredList.Add(fi);
                }
            }
            return filteredList.ToArray();
        }

        private static FileInfo[] GetFilesByFilter(string filter, string locPath)
        {
            DirectoryInfo d = new DirectoryInfo(locPath);
            FileInfo[] fi = d.GetFiles(filter);
            return fi;
        }

        private void CopyFiles(FileInfo[] files, string destPath)
        {
            foreach (FileInfo fi in files)
            {
                bool success = false;
                int i = 0;
                string copyToName = fi.Name;
                string copyToExt = fi.Extension;
                string copyToNameWithoutExt = Path.GetFileNameWithoutExtension(fi.FullName);
                while (!success && i < 100)
                {
                    i++;
                    try
                    {
                        if (File.Exists(Path.Combine(destPath, copyToName)))
                            throw new CopyFileExistsException();
                        File.Copy(fi.FullName, Path.Combine(destPath, copyToName));
                        success = true;
                    }
                    catch (CopyFileExistsException ex)
                    {
                        copyToName = String.Format("{0} ({1}){2}", copyToNameWithoutExt, i, copyToExt);
                    }
                }
            }
        }
    }
    public class CopyFileExistsException : Exception
    {
        public string Message;
    }

}

Ответы [ 5 ]

6 голосов
/ 17 июня 2010

Этот код также «кричит», чтобы его можно было разбить на более мелкие и более специализированные объекты.

Ваш объект CopyJob, похоже, является скорее менеджером списка заданий.Я мог бы изменить имя этого на CopyJobManager или что-то в этом роде.Затем вы можете использовать CopyJob как базовый класс для разных типов фильтров.Общий код, например Execute (), будет определен в базовом классе, а пользовательское поведение, например, Filtering, будет обрабатываться в производных классах.У вас будут TextFilterCopyJob, RegExFilterCopyJob и NoFilterCopyJob.

Когда шаблон Factory может вступить в игру, это когда вы создаете список CopyJobs.У вас может быть объект CopyJobFactory, который берет строку из вашего набора данных и возвращает правильную дочернюю версию CopyJob.CopyJobManager затем будет выполнять свои операции над списком CopyJobs вместо списка строк набора данных.

1 голос
/ 17 июня 2010

Всякий раз, когда я вижу Swithcs или кирпичи Ifs, я делаю поспешный вывод, что по крайней мере можно создать шаблон стратегии.

простой и понятный способ настроить его - использовать словарь <>

в вашем случае вы захотите получить значение ключа на основе имени фильтра, к которому относятся ваши дела, и это будет новый объект фильтров.

теперь вы можете просто передать строкуdictionarys Метод TryGetValue, позволяющий ему получить правильный объект фильтра для вас, boom!

Теперь вы можете инкапсулировать сопоставление фильтров <-> строк и избавить логику и использование фильтров от необходимости видетьлогика поиска правильного объекта!

0 голосов
/ 17 июня 2010

Я бы предложил следующее:

Измените операторы switch (как упомянуто @Jordan)

Добавьте метод расширения для преобразования перечисления FilterType в int и сохраните его в базе данных, а не в строке. Э.Г.

public static class FilterTypeExtensions
{
    public static int AsNumeric(this FilterType filterType)
    {
        return (int)filterType;
    }
}

В качестве второстепенной точки, одиночные скобки ужасны, либо сбросьте скобки, либо используйте правильный интервал / отступ. :)

0 голосов
/ 17 июня 2010

Вот кое-что из того, что я сделал для реализации шаблона Factory

Сначала я создал интерфейс для фильтра:

interface IFileFilter
{
    string GetFilterName();
    string GetFilterReadableName();
    FileInfo[] GetFilteredFiles(string path, string filter);
}

Затем я создал классы под-фильтра для этого интерфейса:

class RegExFileFilter : IFileFilter

{
    #region IFileFilter Members

    public string GetFilterName()
    {
        return "RegExFilter";
    }

    public string GetFilterReadableName()
    {
        return "RegEx Filter";
    }

    public FileInfo[] GetFilteredFiles(string path, string filter)
    {
        DirectoryInfo d = new DirectoryInfo(path);
        FileInfo[] fullFileList = d.GetFiles();
        List<FileInfo> filteredList = new List<FileInfo>();
        Regex rgx = new Regex(filter);
        foreach (FileInfo fi in fullFileList)
        {
            if (rgx.IsMatch(fi.Name))
            {
                filteredList.Add(fi);
            }
        }
        return filteredList.ToArray();
    }

    #endregion
}
class TextFileFilter : IFileFilter
{
    #region IFileFilter Members

    public string GetFilterName()
    {
        return "TextFilter";
    }

    public string GetFilterReadableName()
    {
        return "Text Filter";
    }

    public FileInfo[] GetFilteredFiles(string path, string filter)
    {
        DirectoryInfo d = new DirectoryInfo(path);
        FileInfo[] fi = d.GetFiles(filter);
        return fi;
    }

    #endregion
}
class NoFileFilter : IFileFilter
{
    #region IFileFilter Members

    public string GetFilterName()
    {
        return "TextFilter";
    }

    public string GetFilterReadableName()
    {
        return "Text Filter";
    }

    public FileInfo[] GetFilteredFiles(string path, string filter)
    {
        DirectoryInfo d = new DirectoryInfo(path);
        FileInfo[] fi = d.GetFiles(filter);
        return fi;
    }

    #endregion
}

Тогда я создал Фабрику:

public static IFileFilter FileFilter(string filterName)
{
    switch (filterName)
    {
        case "Text Filter":
            return new TextFileFilter();
        case "RegEx Filter":
            return new RegExFileFilter();
        default:
            return new NoFileFilter();
    }
}
0 голосов
/ 17 июня 2010

Нет ничего плохого в использовании оператора switch, как у вас. Это не крик для любого шаблона проектирования, кроме того, что вы можете поместить его в функцию, чтобы у вас не было одного и того же переключателя дважды.

Переключение будет быстрее, чем при использовании отражения, и проблема, которую вы пытаетесь решить, на самом деле не требует шаблона Factory.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...