我想出这个例子来澄清我的问题。
我们从一个基类开始
/// <summary>
/// Just a silly example class
/// </summary>
class CFileStream
{
protected readonly string FilePath;
public CFileStream(string filePath)
{
FilePath = filePath;
}
public virtual void Write(string s)
{
var stream = GetStream(FilePath);
//etc
}
/// <summary>
/// Take filePath as an argument to make subclassing easier
/// </summary>
protected virtual FileStream GetStream(string filePath)
{
return new FileStream(filePath, FileMode.OpenOrCreate);
}
}为其创建一个子类
/// <summary>
/// Building on top of CFileStream, created an encrypted version
/// </summary>
class CFileStreamEncrypted : CFileStream
{
private readonly string _key;
public CFileStreamEncrypted(string filePath, string key):base(filePath)
{
_key = key;
}
/// <summary>
/// For added complexity, let's also wrap a possible excepton
/// </summary>
public override void Write(string s)
{
try
{
base.Write(s);
}
catch (ImaginaryCryptoException ex)
{
throw new ImaginaryCustomException("bladibla", ex);
}
}
/// <summary>
/// Wrap the base stream in an imaginary crypto class
/// </summary>
protected override FileStream GetStream(string filePath)
{
return new CImaginaryCryptoStream(base.GetStream(filePath), _key);
}
}现在我们希望创建第二个子类,但是这个子类可以与初始文件写入器和加密版本一起使用。
第一个是有意义的
/// <summary>
/// Building on top of CFileStream, created an auto-split version
/// </summary>
class CFileStreamSplit : CFileStream
{
public CFileStreamSplit(string filePath)
: base(filePath)
{
}
protected int Counter;
/// <summary>
/// Close stream and move to next file at the appropriate time(s)
/// </summary>
public override void Write(string s)
{
do
{
Stream stream;
if (ImaginaryBooleanMustSplit)
stream = GetStream(FilePath);
//etc
} while (ImaginaryBooleanDataLeftToWrite);
}
/// <summary>
/// Get base stream but with altered filePath
/// </summary>
protected override FileStream GetStream(string filePath)
{
return base.GetStream(GetNextpath(filePath));
}
/// <summary>
/// Ignore proper extension / file-exists etc.
/// </summary>
protected virtual string GetNextpath(string filePath)
{
return filePath + ++Counter;
}
}第二个(下面)是完全重复的代码,除了构造器,它现在也需要加密密钥。
/// <summary>
/// Build the same auto-split version but this time on top of the encrypted subclass
/// </summary>
class CFileStreamSplitEncrypted : CFileStreamEncrypted
{
public CFileStreamSplitEncrypted(string filePath, string key)
: base(filePath, key)
{
}
/*
* Note that there are no changes below this line
*/
protected int Counter;
/// <summary>
/// Close stream and move to next file at the appropriate time(s)
/// </summary>
public override void Write(string s)
{
do
{
Stream stream;
if (ImaginaryBooleanMustSplit)
stream = GetStream(FilePath);
//etc
} while (ImaginaryBooleanDataLeftToWrite);
}
/// <summary>
/// Get base stream but with altered filePath
/// </summary>
protected override FileStream GetStream(string filePath)
{
return base.GetStream(GetNextpath(filePath));
}
/// <summary>
/// Ignore proper extension / file-exists etc.
/// </summary>
protected virtual string GetNextpath(string filePath)
{
return filePath + ++Counter;
}
}当然,这里有很多方法可以减少重复代码的数量,但我还没有找到“最好的”方法,如果真的有这样的事情的话。那么,在你的观点/经验中,什么是最耗时、最干净、最灵活的方法来解决这个问题呢?
发布于 2013-07-26 02:02:53
对于不同的修改,一种合适的方式可能是组合而不是继承。将你的类设置为只负责一件事,在构造上接受一个基流。
interface ICFileStream
{
void Write(string s);
FileStream GetStream(string filePath);
}
/// <summary>
/// Just a silly example class
/// </summary>
class CFileStream: ICFileStream
{
protected readonly string FilePath;
public CFileStream(string filePath)
{
FilePath = filePath;
}
public void Write(string s)
{
var stream = GetStream(FilePath);
//etc
}
/// <summary>
/// Take filePath as an argument to make subclassing easier
/// </summary>
protected FileStream GetStream(string filePath)
{
return new FileStream(filePath, FileMode.OpenOrCreate);
}
}
/// <summary>
/// Building on top of CFileStream, created an encrypted version
/// </summary>
class CFileStreamEncrypted : ICFileStream
{
private readonly string _key;
private readonly ICFileStream _stream;
public CFileStreamEncrypted(string key, ICFileStream stream)
{
_key = key;
_stream = stream;
}
/// <summary>
/// For added complexity, let's also wrap a possible excepton
/// </summary>
public void Write(string s)
{
try
{
_stream.Write(s);
}
catch (ImaginaryCryptoException ex)
{
throw new ImaginaryCustomException("bladibla", ex);
}
}
/// <summary>
/// Wrap the base stream in an imaginary crypto class
/// </summary>
protected FileStream GetStream(string filePath)
{
return new CImaginaryCryptoStream(_stream.GetStream(filePath), _key);
}
}
class CFileStreamSplit : ICFileStream
{
private readonly ICFileStream _stream;
public CFileStreamSplit(ICFileStream stream)
{
_stream = stream;
}
protected int Counter;
/// <summary>
/// Close stream and move to next file at the appropriate time(s)
/// </summary>
public void Write(string s)
{
do
{
Stream stream;
if (ImaginaryBooleanMustSplit)
stream = GetStream(FilePath);
//etc
} while (ImaginaryBooleanDataLeftToWrite);
}
/// <summary>
/// Get base stream but with altered filePath
/// </summary>
protected FileStream GetStream(string filePath)
{
return _stream.GetStream(GetNextpath(filePath));
}
/// <summary>
/// Ignore proper extension / file-exists etc.
/// </summary>
protected string GetNextpath(string filePath)
{
return filePath + ++Counter;
}
}因此,当您需要拆分加密文件流时:
new CFileStreamSplit(new CFileStreamEncrypted("crypto-awesome-key", new CFileStream("C:\\blah...")));这更加灵活,例如,当您想要添加LoggingCFileStream时,您不需要为每个组合添加单独的类。
https://stackoverflow.com/questions/17864915
复制相似问题