iT邦幫忙

2024 iThome 鐵人賽

DAY 22
0

Combinatorial explosion

簡介

有好幾段程式碼, 根據不同參數的組合而幾乎都在做一樣的事情.

重構前範例

假設有個禮品店員, 根據包裝物的大小, 需要包裝成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)
{
}
  1. 建立PackageBase<TItem>基礎類別, 所有的子類別都要指定Item的類型
  2. 新增泛型的Pack<TItem, TPackage>(TItem item)方法, 並用where限制輸入類型的條件
  3. 透過反射建立PackageBase物件
  4. 移除舊版的Pack方法

為何要重構

達到"Don't Repeat Yourself" 與 "Open-closed" 原則
"Open-closed"是因為未來只要擴充PackageBase子類別就好


上一篇
Introduce Parameter Object 的重構
下一篇
實作Value Type 為 Immutable物件
系列文
程式淨化計畫:痛苦是重構的起源!31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言