熟悉设计模式的看过来,不用类型文件的打开有不同的处理方法,这里应当用什么样的模式?

stonepeter 2006-04-13 11:09:50
我只是了解设计模式的内容,不熟悉。
日前在写一个文本检索的程序,要求能处理文本,WORD,EXCEL文件。
因为处理的方式明显不太一样,文本文件直接打开读就可以了,WORD和EXCEL文件要用专用组件打开来读取中间的文本内容。
万一以后还想读取其他格式的文件的文本内容,还要新增代码。
但是,很明显,我不想改动主程序中的代码,我希望充分利用设计模式带来的好处,最大可能将我以前的代码重用。
但是,我还是不知道这样的方式用什么样的设计模式?
行为模式中的Command模式?也不太像啊。
谢谢所有关注和回答者。
...全文
2667 69 打赏 收藏 转发到动态 举报
写回复
用AI写文章
69 条回复
切换为时间正序
请发表友善的回复…
发表回复
nicolas16 2007-04-08
  • 打赏
  • 举报
回复
mark
Nirvana7 2007-03-20
  • 打赏
  • 举报
回复
mark
icosagon 2006-12-29
  • 打赏
  • 举报
回复
如果想完全不改动已有代码,可以用多态工厂,其实是对静态工厂的改进
说一下思路
工厂类,包含一个静态map,包含纯虚的create函数,在另一函数中根据map调用它
工厂初始化类,设为工厂类的友元,作用维护map,注册产品
IRead类及其子类
子类中嵌套一个从工厂类派生的类,自身实现其创建

这样以后增加新对象的时候只需多实现一个嵌套类,在调用一下工厂初始化类注册一下新产品即可
stonepeter 2006-07-03
  • 打赏
  • 举报
回复
居然成了《程序员》杂志上的推荐贴子了,呵呵,不容易啊。
gorge007 2006-05-12
  • 打赏
  • 举报
回复
OK
robothn 2006-05-11
  • 打赏
  • 举报
回复
mark
objectprogram 2006-05-11
  • 打赏
  • 举报
回复
用c#2.0中的泛型也可以啊.
智商无下限 2006-05-08
  • 打赏
  • 举报
回复
很典型的策略模式吗,呵呵
he_sl 2006-05-08
  • 打赏
  • 举报
回复
mark
stonepeter 2006-05-08
  • 打赏
  • 举报
回复
怎么还有人说是策略模式???
wumingchenchao 2006-05-04
  • 打赏
  • 举报
回复
mark
classjava 2006-04-27
  • 打赏
  • 举报
回复
工厂模式就可以实现
以后只要多建一些具体实现类就可以了
逸学堂 2006-04-26
  • 打赏
  • 举报
回复
今天看书,感觉典型的工厂方法模式
kangji 2006-04-25
  • 打赏
  • 举报
回复
其实楼主的需求可以直接用VBA来实现,应该非常容易搞定(因为都是OFFICE文档,它们都支持VBA宏操作)
stonepeter 2006-04-25
  • 打赏
  • 举报
回复
TO:kangji(尾鱼头)
我也思考过用VBA
可惜我不知道VBA中有没有简单容易提取电子邮箱的正则表达式。
其实本程序最漂亮的部份就是正则表达式,也是本程序最核心的算法。
可以把几句比喻成红花,其他的代码都是小草和绿叶,而工厂模式是整个花园的围栏。
(当然这个正则表达式可能还有不足)
Regex r = new Regex(@"(?<email>[^@\s:]+@\S+)");
foreach ( Match m in r.Matches(s) )
{
...
}
oo 2006-04-25
  • 打赏
  • 举报
回复
mark
KDE 2006-04-25
  • 打赏
  • 举报
回复
VISITOR + PROXY
stonepeter 2006-04-24
  • 打赏
  • 举报
回复
/////现在的IReader/TxtReader/DocReader/XlsReader类//////
/// <summary>
/// 文件读取接口
/// </summary>
public abstract class IReader
{
public IReader(string filename) // 创建实例的时候就一定要文件名
{
_filename = filename;
}
protected string _filename=""; // 输入文件名
protected string _outfilename=@"c:\Temp.txt"; // 输出文件名
public abstract bool GetAllEmails(int EmailsPerLine); // 每行EmailsPerLine个电子邮件
private static int counts=0; // 在一个实例的过程中计算总数~
protected void GetEmails(int EmailsPerLine, StreamReader sr, StreamWriter sw)
{
string s;
while ((s=sr.ReadLine()) != null)
{
Regex r = new Regex(@"(?<email>[^@\s:]+@\S+)");

foreach ( Match m in r.Matches(s) )
{
counts++;
if( (counts%EmailsPerLine)==1 )
sw.Write( m.Groups["email"].Value );
else
sw.Write( "," + m.Groups["email"].Value );
if( (counts%EmailsPerLine)==0 )
sw.WriteLine(); // 每EmailsPerLine个换行.
}
}
}
}
/// <summary>
/// 文本文件类
/// </summary>
public class TxtReader:IReader
{
public TxtReader(string filename):base(filename){}
public override bool GetAllEmails(int EmailsPerLine)
{
try
{
if (File.Exists(_outfilename))
{
File.Delete(_outfilename);
}
using ( StreamWriter sw = File.CreateText( _outfilename ) ) // 直接将结果写入文件
{
if( sw==null ) return false;
using (StreamReader sr = new StreamReader(_filename))
{
if( sr==null ) return false;
GetEmails(EmailsPerLine, sr, sw);
}
}
}
catch
{
return false;
}


return true;
}

}
public class DocReader:IReader
{
private string _outtxtfile=@"c:\temp_doc.txt"; // 暂存盘文件

public DocReader(string filename):base(filename){}
public override bool GetAllEmails(int EmailsPerLine)
{
#region 将WORD文件另存为TXT文件
//String inFileName = txtBoxInputFile.Text;
if (!File.Exists(_filename))
return false;

//Set some vars
object fileName = _filename;
object fileSaveName = _outtxtfile; //_outfilename;//_filename.Substring(0,

object vk_read_only = false;
object vk_visible = true;
object vk_true = true;
object vk_false = false;
object vk_dynamic = 2;

object missing = System.Reflection.Missing.Value;
object vk_range = missing;
object vk_to = missing;
object vk_from = missing;
//Microsoft.Office
Word.ApplicationClass vk_word_app = new Word.ApplicationClass();
// Open the document that was chosen by the dialog
Word.Document aDoc = null;
try
{
aDoc = vk_word_app.Documents.Open(
ref fileName, ref missing,
ref vk_read_only, ref missing,
ref missing, ref missing,
ref missing, ref missing,
ref missing, ref missing,
ref missing, ref vk_visible,
ref missing, ref missing,
ref missing);
}
catch
{
return false;
}
try
{
// 参看:http://msdn2.microsoft.com/en-us/library/microsoft.office.tools.word.document.saveas.aspx
object vk_saveformat = Word.WdSaveFormat.wdFormatUnicodeText;

aDoc.SaveAs(ref fileSaveName, ref vk_saveformat,
ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing);
}
catch
{ //MessageBox.Show("Error : "+ex.ToString());}
return false;
}
finally
{ //Don't forget to close everything up...
if (aDoc != null)
{
aDoc.Close(ref vk_false, ref missing, ref missing);
}
vk_word_app.Quit(ref vk_false,ref missing,ref missing);
}
#endregion

// 借用已经实现的TXT文件EMail提取器,完成提取的工作。
TxtReader tReader = new TxtReader(_outtxtfile);
return tReader.GetAllEmails(EmailsPerLine);
}
}
public class XlsReader:IReader
{
private string _outtxtfile=@"c:\temp"; // 暂存盘文件
public XlsReader(string filename):base(filename){}
public override bool GetAllEmails(int EmailsPerLine)
{
#region 将EXCEL文件另存为TXT文件
Excel.Application xApp = new Excel.ApplicationClass();
xApp.Visible = false;

object vk_false = false;
object vk_readonly = true;

// 打开文件
Excel.Workbook xBook = null;
try
{
xBook = xApp.Workbooks.Open(_filename,
Missing.Value,vk_readonly,Missing.Value,Missing.Value,Missing.Value,Missing.Value,Missing.Value,
Missing.Value,Missing.Value,Missing.Value,Missing.Value,Missing.Value,Missing.Value,Missing.Value);
}
catch
{
return false;
}

object vk_saveformat = Excel.XlFileFormat.xlUnicodeText;
int iSheets=0;
ArrayList sTemps=new ArrayList();
try
{
foreach( Excel.Worksheet xSheet in xBook.Sheets )
{
string sFilename = _outtxtfile+iSheets+".txt";
sTemps.Add( sFilename );
if( File.Exists( sFilename ) )
File.Delete( sFilename );

xSheet._SaveAs( sFilename,vk_saveformat,
Missing.Value,Missing.Value,Missing.Value,Missing.Value,Missing.Value,Missing.Value,Missing.Value);
iSheets++;
}
}
catch
{ //MessageBox.Show("Error : "+ex.ToString());}
return false;
}
finally
{ //Don't forget to close everything up...
if (xBook != null)
{
xBook.Close(vk_false, Missing.Value, Missing.Value);
}
xApp.Quit();
}
#endregion

try
{
if (File.Exists(_outfilename))
{
File.Delete(_outfilename);
}
using ( StreamWriter sw = File.CreateText( _outfilename ) ) // 直接将结果写入文件
{
if( sw==null ) return false;
foreach( string sFile in sTemps ) // 依次打个各表单保存的文本文件
{
using (StreamReader sr = new StreamReader( sFile ))
{
if( sr==null ) return false;
GetEmails(EmailsPerLine, sr, sw);
}
File.Delete(sFile);
}
}
}
catch
{
return false;
}

return true;
}

}
////////////////////////////////////////////////////////////////////
//上面代码中关于设计模式的知识//
1、每个子类都实现了public abstract bool GetAllEmails(int EmailsPerLine);方法,这个方法在主程序中调用了。参数EmailsPerLine-每行"若干"个电子邮件
2、每个子类都用到了
1)计数器(在一个类实例中是全局的--这句不懂???呵呵,等你看到Excel的Sheet处理的时候就明白了)
private static int counts=0; // 在一个实例的过程中计算总数~
2)从sr文件流中读数据,放到sw文本文件中去,每EmailsPerLine个的时候换一行:
protected void GetEmails(int EmailsPerLine, StreamReader sr, StreamWriter sw);
//////////////////////////////////////////////////////////////////////////
//上面代码中关于各种文档操作的知识
1、TEXT文件:大量使用File.Exists File.Delete StreamReader StreamWriter(System.IO名字空间)
2、Word文件
1)新增COM引用"Microsoft Word 10.0 Object Library"
2)使用Word.ApplicationClass.Document.Open方法打开Word文件
3)使用Word.Document.SaveAs方法另存成Unicode文本文件
// 参看:http://msdn2.microsoft.com/en-us/library/microsoft.office.tools.word.document.saveas.aspx
4)借用TxtReader类,从另存成文本的Word文件中提取Emails
3、Excel文件
1)新增COM引用"Microsoft Excel 10.0 Object Library"
2)使用Excel.Application.Workbooks.Open方法打开Excel文件
3)使用Excel.Worksheet._SaveAs方法及foreach函数,依次将Worksheets另存为不用名字的Unicode文本文件(文件名在ArrayList中)
4)使用GetEmails(int EmailsPerLine, StreamReader sr, StreamWriter sw)方法及foreach函数将步骤3)中的每一个文本文件打开,抓取所有的Emails.
////////////////////////////////////////////////////////////////////////////////
核心技术都说了!他们用了一下还可以。
stonepeter 2006-04-24
  • 打赏
  • 举报
回复
////////////程序入口方法///////////////
////使用静态的工厂方法打开文件同时,按照文件类型建立所要的Reader实例////
/////执行完成GetAllEmails方法之后,用写字板打开保存的电子邮箱文本文件方便工作人员使用////
private void bt_get_Click(object sender, System.EventArgs e)
{
IReader reader = DocTypeFactory.GetDocTypeInstance( textBox1.Text );
if( reader!=null )
{
if( reader.GetAllEmails(EmailsPerLine) )
{
MessageBox.Show(@"电子邮件提取成功,已经全都保存到c:\temp.txt文件中去了!");

// http://www.programfan.com/article/showarticle.asp?id=2209
System.Diagnostics.ProcessStartInfo Info = new System.Diagnostics.ProcessStartInfo();
//设置外部程序名
Info.FileName = "notepad.exe";
//设置外部程序的启动参数(命令行参数)为test.txt
Info.Arguments = "temp.txt";
//设置外部程序工作目录为 C:\
Info.WorkingDirectory = "C:\\";
//声明一个程序类
System.Diagnostics.Process Proc ;
try
{
//
//启动外部程序
//
Proc = System.Diagnostics.Process.Start(Info);
}
catch
{
MessageBox.Show("系统找不到指定的程序文件。");
return;
}
}
else
MessageBox.Show("提取失败,请另选文件!");
}
}
///////////////////////////////////////////////////////////////////
stonepeter 2006-04-24
  • 打赏
  • 举报
回复
我的这个贴子引来了好多星星的专家们的回复真是很荣幸!
不过我很多说用策略模式,适配器模式等其他的模式的,我都看不太懂。我也明白我的设计中有很多不足。
-----------------------------------------
软件要求实现的功能:能从文本文件、Word文件、Excel文件中提取出所有的“电子邮箱”,将提取的结果放入一个文本文件,文本文件中的每一行放若干个电子邮箱,之间用逗号(,)分开。
目的:为了方便工作人员大批量发送电子邮件的时候不要一次次的COPY PASTE,而是一次COPY一行,再PASTE一行,极大的方便工作人员发邮件。比如,原来有800个电子邮件分布在*.XLS文件格式的通讯录中,以前的办法是做800次COPY/PASTE,还要找到email所在文档中的位置,很麻烦。现在用了本软件,把email自动抓出来,分20个一行放好(有的邮箱一次最多只能发20个邮件),只要COPY/PASTE40次,就可以完成了。将原来本来要一上午才能完成的事情,半个小时就完成了。
----------------以上是软件功能描述-----------
这两天对整个软件做了大的改动,多抓了一些未获得的错误。具体新增功能如下:
1、新加了Excel文件的处理。难点:Excel文件中的内容是保存在多个Sheet里面的,我用foreach遍历了所有Sheet。这样和前面对Txt文件和Word文件的处理方法有了一些变化了。
办法,将TxtReader类中的private void GetEmails(int EmailsPerLine, StreamReader sr, StreamWriter sw)方法移动了了IReader基类里去了。
2、新增了对每行电子邮件数目的设定。前面的程序中都固定了值(5)。现在直接从CONFIG文件中读取。注:因为我的.NET Framework是1.1,所以CONFIG文件中的内容只能读取,如果用.NET Framework2.0的话,可以把上次的设定值保存在CONFIG文件中。
加载更多回复(49)

5,530

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 模式及实现
社区管理员
  • 模式及实现社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧