现在的位置: 首页 > 综合 > 正文

小小菜学设计模式之 文件名管理器 ver 1.1 解耦

2012年09月23日 ⁄ 综合 ⁄ 共 4754字 ⁄ 字号 评论关闭



 

先分析一下,文件名管理系统分为哪几个部分,

初步分析是界面(client),和文件名处理两个部分,那么client不应该出现文件名的处理的,

(但是界面逻辑可以保留下来,比如点击"启用编号"就将相应的选项打开)

因此,可以先尝试着抽象出一个文件名处理类,

命名为FileNameManager,此类的主要功能是完成:

1 在输入文件完整路径后(以字符串数组形式),然后加载改文件到相应的List对象中,

2 List中的对象进行改名(只考虑批量更改的情况)

在其中定义两个功能的函数来处理就行

 

而客户端则可以声明一个FileNameManager来处理它的需求

基于此可以画出类图

对于文件名管理器而言,它并不需要知道客户端的存在,而客户端需要知道文件名管理器,因为需要它来管理自己的文件名,因此他们之间是关联的关系

整个类代码如下:

 

FileNameManager类

class FileNameManager
{
private List<FileInfo> curAddedFiles; //当前添加的文件
private FileInfo curFileInf; //当前文件
/// <summary>
/// 初始化文件名管理类
/// </summary>
/// <param name="curAddedFiles">当前添加的文件</param>
/// <param name="curFileInf">当前选择文件</param>
public FileNameManager(List<FileInfo> curAddedFiles, FileInfo curFileInf)
{
this.curAddedFiles = curAddedFiles;
this.curFileInf = curFileInf;
}
/// <summary>
/// 添加文件(按文件名数组)
/// </summary>
/// <param name="files"></param>
public void AddFiles(string[] files)
{
try
{

for (int i = 0; i < files.Length; i++)
{
//判断当前列表中是否已经存在该文件信息
if (!curAddedFiles.Contains(new FileInfo(files[i])))
{
curAddedFiles.Add(
new FileInfo(files[i]));
}
}
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 添加文件(按文件信息对象)
/// </summary>
/// <param name="files"></param>
public void AddFiles(FileInfo[] files)
{
try
{

for (int i = 0; i < files.Length; i++)
{
//判断当前列表中是否已经存在该文件信息
if (!curAddedFiles.Contains(files[i]))
{
curAddedFiles.Add(files[i]);
}
}
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 添加文件(按目录对象)
/// </summary>
/// <param name="files"></param>
public void AddFiles(DirectoryInfo directory)
{
try
{
FileInfo[] tmpFileInfos
= directory.GetFiles();
foreach (var item in tmpFileInfos)
{
if (!curAddedFiles.Contains(item))
{
curAddedFiles.Add(item);
}
}
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 为文件改名
/// </summary>
/// <param name="changingMethod">改名方式(前缀,后缀)</param>
/// <param name="digits">位数</param>
/// <param name="filename">以此为基础改名</param>
public void ChangeNames(string changingMethod, int digits, string filename)
{
if (curAddedFiles == null || curAddedFiles.Count == 0)
{
throw new Exception("还没有添加任何文件!");
}
string setDigit = "";
for (int i = 0; i < digits; i++)
{
setDigit
+= "0";
}
switch (changingMethod)
{
//以前缀形式添加
case "Prefix":
for (int i = 0; i < curAddedFiles.Count; i++)
{
curAddedFiles[i].MoveTo(curFileInf.DirectoryName
+ "\\" +
string.Format("{0:" + setDigit + "} ", i) + filename + curFileInf.Extension);
//↑ 拼接一段格式化字符串 比如如果你设置的是两位那么拼接的结果就是 ("{0:00"} ", i) 那么文件名也将显示为 01,02,下同
}
break;
//以后缀形式添加
case "Postfix":
for (int i = 0; i < curAddedFiles.Count; i++)
{
string name = curFileInf.DirectoryName + "\\" + filename +
string.Format(" {0:" + setDigit + "}", i) + curFileInf.Extension;
curAddedFiles[i].MoveTo(name);
}
break;
default:
break;
}
}

/// <summary>
/// 格式化文件大小
/// </summary>
/// <param name="fileSize">文件大小</param>
/// <returns>格式化后的文件大小</returns>
public static String FormatFileSize(Int64 fileSize)
{
if (fileSize < 0)
{
throw new ArgumentOutOfRangeException("fileSize");
}
else if (fileSize >= 1024 * 1024 * 1024)
{
return string.Format("{0:########0.00} GB", ((Double)fileSize) / (1024 * 1024 * 1024));
}
else if (fileSize >= 1024 * 1024)
{
return string.Format("{0:####0.00} MB", ((Double)fileSize) / (1024 * 1024));
}
else if (fileSize >= 1024)
{
return string.Format("{0:####0.00} KB", ((Double)fileSize) / 1024);
}
else
{
return string.Format("{0} bytes", fileSize);
}
}
}

 

完成了文件名管理这个类,界面处理逻辑就要清晰的多了

 

client主要代码


System.Windows.Forms.FolderBrowserDialog fbd
= new System.Windows.Forms.FolderBrowserDialog();
OpenFileDialog ofd
= new OpenFileDialog();
/*把它们俩作为成员变量的好处是在整个窗口运行期间,都会保存该选定的文件和添加的文件的状态,如果是局部变量我就要不停的获取状态*/
private List<FileInfo> curSelectedFiles = new List<FileInfo>(); //当前选定的文件
private List<FileInfo> curAddedFiles = new List<FileInfo>(); //当前添加的文件
FileNameManager fnm;
...

//打开文件
private void btnOpen_Click(object sender, RoutedEventArgs e)
{
ofd.Multiselect
= true;
if (ofd.ShowDialog() == true)
{
fnm.AddFiles(ofd.FileNames);
lstFilelist.Items.Refresh();
lstFilelist.ItemsSource
= curAddedFiles;
lstFilelist.DisplayMemberPath
= "Name";
}
}
//打开文件夹
private void button1_Click(object sender, RoutedEventArgs e)
{
if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
DirectoryInfo di
= new DirectoryInfo(fbd.SelectedPath);
fnm.AddFiles(di);
}
lstFilelist.Items.Refresh();
//注意,必须要重新创建视图。否则不会在该listbox中显示新的数据源
lstFilelist.ItemsSource = curAddedFiles;
lstFilelist.DisplayMemberPath
= "Name";
}

...


//更改一个文件
private void btnSingle_Click(object sender, RoutedEventArgs e)
{
if (fnm.CurFileInf == null)
{
MessageBox.Show(
"您还没有选定一个文件!请先选择!");
return;
}
fnm.CurFileInf.MoveTo(fnm.CurFileInf.DirectoryName
+ "\\" + txtFileName.Text + fnm.CurFileInf.Extension);
}
//批量更改
private void btnBatch_Click(object sender, RoutedEventArgs e)
{

if (string.IsNullOrEmpty(txtFileName.Text))
{
MessageBox.Show(
"请先指定一个文件名");
return;
}
if (MessageBox.Show("该功能将以您输入的文件名为标准 为所选定的文件加上您指定的前缀或后缀","注意!",MessageBoxButton.YesNo)==MessageBoxResult.No)
{
return;
}
fnm.ChangeNames(rdoPrefix.IsEnabled
? "Prefix" : "Postfix",
Convert.ToInt32( txtDigit.Text), txtFileName.Text);
}

...

完成了之后也就完成了功能和界面的解耦,

但是依然存在很多问题,

首先,除了抽象出一个类以外,并没有使用任何其他面向对象的知识或者是设计模式

如果我要为filenameManager添加功能的话必须要修改此类

因此这就不满足"开放-封闭"的原则,

当然这样的文件名管理类的不满足单一职责原则,因为此类完成了好几个功能.

其次,该类的设计同样没有按照依赖倒转的原则(即依赖抽象)来设计--只有一个类何来抽象?

 

这样的设计显然是非常失败的.

 

下周继续重构~~~

抱歉!评论已关闭.