有好幾段程式碼, 根據不同參數的組合而幾乎都在做一樣的事情.
假設有個禮品店員, 根據包裝物的大小, 需要包裝成3種類型:
public class Clerk
{
public BigPackage Pack(BigItem item)
{
return new BigPackage(item);
}
public MediumPackage Pack(MediumItem item)
{
return new MediumPackage(item);
}
public SmallPackage Pack(SmallItem item)
{
return new SmallPackage(item);
}
}
public class SmallItem
{
}
public class MediumItem
{
}
public class BigItem
{
}
public class SmallPackage
{
private SmallItem _item;
public SmallPackage(SmallItem item)
{
_item = item;
}
}
public class MediumPackage
{
private MediumItem _item;
public MediumPackage(MediumItem item)
{
_item = item;
}
}
public class BigPackage
{
private BigItem _item;
public BigPackage(BigItem item)
{
_item = item;
}
}
可以看到, 光是要包裝Pack
, 就宣告三種函數來完成幾乎一樣的事情
因此, 我們將這行為透過泛型與反射, 來達到更優雅的程式碼:
public class Clerk
{
public TPackage Pack<TItem, TPackage>(TItem item) where TPackage : PackageBase<TItem>
where TItem: class
{
return (TPackage)Activator.CreateInstance(typeof(TPackage), item);
}
}
public class SmallItem
{
}
public class MediumItem
{
}
public class BigItem
{
}
public abstract class PackageBase<TItem>
{
protected TItem item;
public PackageBase(TItem item)
{
this.item = item;
}
}
public class SmallPackage(SmallItem item) : PackageBase<SmallItem>(item)
{
}
public class MediumPackage(MediumItem item) : PackageBase<MediumItem>(item)
{
}
public class BigPackage(BigItem item) : PackageBase<BigItem>(item)
{
}
PackageBase<TItem>
基礎類別, 所有的子類別都要指定Item的類型Pack<TItem, TPackage>(TItem item)
方法, 並用where
限制輸入類型的條件PackageBase
物件Pack
方法達到"Don't Repeat Yourself" 與 "Open-closed" 原則
"Open-closed"是因為未來只要擴充PackageBase
子類別就好