使用简单工厂写一个可复用的批量文件修改工具

简介:

前段日子忙活站点Theme的更改,到发布的时候有个问题难住了我,我要修改四十多个Theme的配置文件,这些配置文件也不在一处,整理出来打包很麻烦,而且本地环境和生产环境里面很多配置都不相同,不能通过简单把全部文件粘贴过去这种方式替换生产环境的配置文件,只能去修改,后来频繁的修改Theme,终于意识到要写个工具了,之前也有一些修改文件的工具,但都是各行其是,痛定思痛决定写一个可复用的批量文件修改工具,当然本文的重点并不在于怎么查找、修改文件,而在于怎么复用。

最开始编程的时候听说过设计模式,急不可耐的读了一番,说实话几乎没有收获,不明白为什么要用设计模式,工作两年后再读设计模式,不敢说收获有多大,但是重构了很多以前的代码,感觉不错,后来自己就情不自禁的在使用一些设计模式了,这个简单的小工具,工厂模式又帮了大忙

需求

我希望做出来的效果是这样的

image

1. 可以在某个文件夹下搜索文件,而不是检索整个硬盘(这个是当然)

2. 不仅仅是按照文件全名搜索,还可以使用一些通配符

3. 能够自己决定是否搜索子文件夹

这些都是框架部分,至于怎么去修改文件,肯定只有开发者自己知道,所以这个工具还得有开发者在框架下不影响其它算法,而拓展自己所需算法的功能。也就是说当我想批量修改某些文件的时候我可以仅仅写一个如何修改文件的算法,而不用关注与怎么搜索神马的,同时拓展部分还不能影响其它算法。

基础框架

需求其实很简单,看看怎么实现,我做的solution目录结构是这样的

image

FileUtility.cs

Base文件夹下的FileUtility.cs封装了搜索文件的方法,写的不太好,凑活能用

复制代码
public class FileUtility
    {
        public static List<string> GetAllFiles(string path, string pattern, bool searchChildFolder)
        {
            List<string> names = new List<string>();
            DirectoryInfo di = new DirectoryInfo(path);

            if (!searchChildFolder)
            {
                FileInfo[] fis = di.GetFiles(pattern);
                foreach (FileInfo fi in fis)
                {
                    names.Add(fi.FullName);
                }
            }
            else
            {
                GetFile(path, pattern, names);
            }
            return names;
        }

        public static void GetFile(string path, string pattern, List<string> names)
        {
            DirectoryInfo di = new DirectoryInfo(path);
            string[] patterns=pattern.Split(new char[]{'|',','},StringSplitOptions.RemoveEmptyEntries);
            foreach (string p in patterns)
            {
                FileInfo[] fis = di.GetFiles(p.Trim());
                foreach (FileInfo fi in fis)
                {
                    names.Add(fi.FullName);
                }
            }

            DirectoryInfo[] dis = di.GetDirectories();
            if (dis.Length != 0)
            {
                foreach (DirectoryInfo _di in dis)
                {
                    GetFile(_di.FullName, pattern, names);
                }
            }
        }
    }
复制代码

Algorithm

Algorithm 这个project Assembly name 是SSTool.Algorithm,存放所有修改文件的算法,Base文件夹下的IAlgorithm是所有算法都要实现的接口

public interface IAlgorithm
    {
        void execute(List<string> files);
    }

DemoAlgorithem.cs是一个简单的示例算法,文件内写一行数据

复制代码
public class DemoAlgorithem:IAlgorithm
    {

        public void execute(List<string> files)
        {
            foreach (string path in files)
            {
                using (StreamWriter sw = new StreamWriter(path, false))
                {
                    sw.WriteLine("This is a text.");
                }
            }
        }
    }
复制代码

 

每添加一个算法就需要在AlgorithmConf.xml添加一条记录

<?xml version="1.0" encoding="utf-8" ?>
<algorithms>
    <item key="Demo" algorithm="SSTool.Algorithm.DemoAlgorithem" />
</algorithms>

这是为后面工厂模式反射获取所有算法做准备

ArithmeticFactory.cs

这个是算法的工产类,用于生成算法对象实例,也就是工厂模式中的工厂类了,IAlgorithm是产品类接口,而DemoAlgorithem是一个具体产品,看看怎么生产算法产品吧

我使用了反射的方式获取算法实例,代码很简单

复制代码
public IAlgorithm CreateUpdateAlgorithm(string key)
        {
            Assembly assembly = Assembly.Load("SSTool.Algorithm");
            Dictionary<string, string> map = GetConf("AlgorithmConf.xml");
            IAlgorithm algorithm = (IAlgorithm)assembly.CreateInstance(map[key]);
            return algorithm;
        }

        public Dictionary<string, string> GetConf(string path)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load("AlgorithmConf.xml");
            XmlNodeList nodes = doc.SelectNodes("//item");
            Dictionary<string, string> map = new Dictionary<string, string>();
            foreach (XmlNode node in nodes)
            {
                map.Add(node.Attributes["key"].Value, node.Attributes["algorithm"].Value);
            }
            return map;
        }
复制代码

 

MainFrame.cs

MainFrame.cs用于生成外观及响应事件

为类添加一个属性,用于获取工厂实例

复制代码
private ArithmeticFactory factory;
        public ArithmeticFactory Factory
        {
            get
            {
                if (factory != null)
                {
                    return factory;
                }
                else
                {
                    factory = new ArithmeticFactory();
                    return factory;
                }
            }
        }
复制代码

在Load事件处理程序中使用工厂的GetConf获取所有配置,把key绑定到界面选择算法的Combobox中

复制代码
protected override void OnLoad(EventArgs e)
        {
            Dictionary<string, string> map = Factory.GetConf("AlgorithmConf.xml");
            this.cmbArithmetic.Items.Clear();
            foreach (KeyValuePair<string, string> pair in map)
            {
                this.cmbArithmetic.Items.Add(pair.Key);
            }
            base.OnLoad(e);
        }
复制代码

 

按钮

1.点击 “Select”按钮的时候调出选择文件夹窗口

复制代码
private void btnSelect_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog dialog = new FolderBrowserDialog();
            dialog.Description = "Select Folder Path";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                this.txtPath.Text = dialog.SelectedPath;
            }
        }
复制代码

2. 点击 “Search” 按钮的时候根据文件夹及Search pattern 搜索文件列表并显示在下面列表中

复制代码
dgvFiles.Columns.Clear();
            List<string> names = FileUtility.GetAllFiles(this.txtPath.Text, this.txtPattern.Text.Trim(), this.ckbRecursive.Checked);
            DataTable dt = new DataTable();
            dt.Columns.Add("File");
            foreach (string name in names)
            {
                DataRow dr = dt.NewRow();
                dr[0] = name;
                dt.Rows.Add(dr);
            }
            dgvFiles.DataSource = dt;
            dgvFiles.Columns[0].Width = dgvFiles.Width;
            for (int i = 0; i < dgvFiles.Rows.Count; i++)
            {
                dgvFiles.Rows[i].Selected = true;
            }
复制代码

3. 在界面上筛选搜索结果,选择算法,点击“Update”按钮,做一些输入验证工作后更新文件,更新算法实例使用工厂获得

复制代码
private void btnUpdate_Click(object sender, EventArgs e)
        {
            string error = ValidateInput();
            if (error == null)
            {
                IAlgorithm algorithm 
= Factory.CreateUpdateAlgorithm(this
.cmbArithmetic.SelectedItem.ToString());
                List<string> files = new List<string>();
                for (int i = 0; i < dgvFiles.Rows.Count; i++)
                {
                    if(dgvFiles.Rows[i].Selected ==true)
                    {
                        files.Add(dgvFiles.Rows[i].Cells[0].Value.ToString());
                    }
                }
                algorithm.execute(files);
                this.panDisplay.Enabled = false;
                this.progressUpdate.Visible = true;
                this.progressUpdate.Value = 0;
                this.progressUpdate.Visible = false;
                this.panDisplay.Enabled = true;
                MessageBox.Show("Done!", "Update");
            }
            else
            {
                MessageBox.Show(error, "Error");
            }
        }
复制代码

最后

这样一个简单的文件批量修改工具就完成了,点击这里下载源码,其实这个工具很简单,没任何高明之处,反而本着发布去写的小工具甚至有些粗糙,只是想借此说明几点

1. 设计模式与我们日常编程工作并不是遥不可及的,设计模式并不只是架构师的菜,只要认真发觉,我们每天使用的类库中都包含很多设计模式,有时候我们也在使用了,只是没发现

2. 设计模式的学习并不是看几本书、在网上看个大牛写的一系列教程就可以做到的,而在于我们对自己写的代码精益求精,发现违背设计原则的地方不断重构,结合理论指导,自然能够用出设计模式,一旦设计模式是自己慢慢演化去代码得来,相信大家就不在会问为什么要用这个模式、用了有什么好处、什么场景下用这个设计模式了。

纸上得来终觉浅,绝知此事要躬行。


    本文转自魏琼东博客园博客,原文链接:http://www.cnblogs.com/dolphinX/p/3320792.html,如需转载请自行联系原作者

相关文章
|
Prometheus 监控 Cloud Native
在 HBase 集群中,Prometheus 通常监控哪些类型的性能指标?
在 HBase 集群中,Prometheus 通常监控哪些类型的性能指标?
270 2
|
消息中间件 安全 Java
Zookeeper的SASL认证最佳实践
Zookeeper的SASL认证最佳实践
4806 0
Zookeeper的SASL认证最佳实践
|
4天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
15天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1309 5
|
1天前
|
监控 JavaScript Java
基于大模型技术的反欺诈知识问答系统
随着互联网与金融科技发展,网络欺诈频发,构建高效反欺诈平台成为迫切需求。本文基于Java、Vue.js、Spring Boot与MySQL技术,设计实现集欺诈识别、宣传教育、用户互动于一体的反欺诈系统,提升公众防范意识,助力企业合规与用户权益保护。
|
14天前
|
机器学习/深度学习 人工智能 前端开发
通义DeepResearch全面开源!同步分享可落地的高阶Agent构建方法论
通义研究团队开源发布通义 DeepResearch —— 首个在性能上可与 OpenAI DeepResearch 相媲美、并在多项权威基准测试中取得领先表现的全开源 Web Agent。
1343 87
|
1天前
|
JavaScript Java 大数据
基于JavaWeb的销售管理系统设计系统
本系统基于Java、MySQL、Spring Boot与Vue.js技术,构建高效、可扩展的销售管理平台,实现客户、订单、数据可视化等全流程自动化管理,提升企业运营效率与决策能力。
|
3天前
|
弹性计算 安全 数据安全/隐私保护
2025年阿里云域名备案流程(新手图文详细流程)
本文图文详解阿里云账号注册、服务器租赁、域名购买及备案全流程,涵盖企业实名认证、信息模板创建、域名备案提交与管局审核等关键步骤,助您快速完成网站上线前的准备工作。
189 82
2025年阿里云域名备案流程(新手图文详细流程)