質問を明確にするためにこの例を思いつきました
基本クラスから始めます
/// <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);
}
}
ここで、2 番目のサブクラスを作成しますが、これは最初のファイルライターと暗号化されたバージョンで動作します。
最初のものは理にかなっている
/// <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;
}
}
2 つ目 (この下) は、暗号化キーも必要とするコンストラクターを除いて、完全に重複したコードです。
/// <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;
}
}
もちろん、ここで重複コードの量を減らす方法はたくさんありますが、そのようなことがあったとしても、「最善の」方法をまだ見つけていません。そう; あなたの意見/経験において、この問題を回避するための最も時間がかからず、最もクリーンで、最も柔軟な方法は何ですか?