在程式碼區塊使用不同的冗長的if/else/switch判斷條件, 該函數的複雜度越來越大.
假設有一個作業系統, 帳號有管理員與普通使用者兩種角色. 當普通使用者要求權限, 需要經過層層的權限狀態判斷, 才能轉換到下一個權限狀態, 或者權限狀態被拒絕轉換.
以下是SystemPermission與相關類別的範例
public class SystemPermission
{
    public static readonly string REQUESTED = "REQUESTED";
    public static readonly string CLAIMED = "CLAIMED";
    public static readonly string GRANTED = "GRANTED";
    public static readonly string DENIED = "DENIED";
    public static readonly string UNIX_REQUESTED = "UNIX_REQUESTED";
    public static readonly string UNIX_CLAIMED = "UNIX_CLAIMED";
    private SystemAdmin _admin;
    private SystemProfile _profile;
    private SystemUser _requestor;
    public SystemPermission(SystemAdmin admin, SystemUser requestor, SystemProfile profile)
    {
        _admin = admin;
        _requestor = requestor;
        _profile = profile;
        State = REQUESTED;
        IsGranted = false;
        NotifyAdminOfPermissionRequest();
    }
    public string State { get; private set; }
    public bool IsGranted { get; private set; }
    public bool IsUnixPermissionGranted { get; private set; }
    private void NotifyAdminOfPermissionRequest()
    {
    }
    public void ClaimedBy(SystemAdmin admin)
    {
        if (State != REQUESTED && State != UNIX_REQUESTED)
        {
            return;
        }
        WillBeHandledBy(admin);
        if (State == REQUESTED)
        {
            State = CLAIMED;
        }
        else if (State == UNIX_REQUESTED)
        {
            State = UNIX_CLAIMED;
        }
       
    }
    private void WillBeHandledBy(SystemAdmin admin)
    {
        _admin = admin;
    }
    public void DeniedBy(SystemAdmin admin)
    {
        if (State != CLAIMED && State != UNIX_CLAIMED) return;
        if (_admin != admin) return;
        IsGranted = false;
        IsUnixPermissionGranted = false;
        State = DENIED;
        NotifyUserOfPermissionRequestResult();
    }
    private void NotifyUserOfPermissionRequestResult()
    {
    }
    public void GrantedBy(SystemAdmin admin)
    {
        if (State != CLAIMED && State != UNIX_CLAIMED) return;
        if (_admin != admin) return;
        if (_profile.IsUnixPermissionRequired && State == UNIX_CLAIMED)
        {
            IsUnixPermissionGranted = true;
        }
        else if (_profile.IsUnixPermissionRequired && IsUnixPermissionGranted)
        {
            State = UNIX_REQUESTED;
            NotifyUserOfPermissionRequestResult();
            return;
        }
        State = GRANTED;
        IsGranted = true;
        NotifyUserOfPermissionRequestResult();
    }
}
public class SystemAdmin
{
}
public class SystemProfile
{
    public bool IsUnixPermissionRequired { get; set; } = false;
}
public class SystemUser
{
}
可以看到, GrantedBy()函數需要檢查State、是否為_admin、_profile的IsUnixPermissionRequired與變數IsUnixPermissionGranted等參數判斷.ClaimedBy()也是依據State條件做這種狀態轉換.
所以, 以這種範例來看, 如果今天狀態更多種, 上述的狀態轉移函數是不是就更複雜?
我們將狀態轉換邏輯成各自的處理類別, 以管理員授權權限的範例, 可以分出1種基礎類別與6種子類別:
public abstract class PermissionState
{
    private readonly string _name;
    protected PermissionState(string name)
    {
        _name = name;
    }
    public static readonly PermissionState REQUESTED = new PermissionRequested();
    public static readonly PermissionState CLAIMED = new PermissionClaimed();
    public static readonly PermissionState GRANTED = new PermissionGranted();
    public static readonly PermissionState DENIED = new PermissionDenied();
    public static readonly PermissionState UNIX_REQUESTED = new UnixPermissionRequested();
    public static readonly PermissionState UNIX_CLAIMED = new UnixPermissionClaimed();
    public override string ToString()
    {
        return _name;
    }
    public virtual void ClaimedBy(SystemAdmin admin, SystemPermission permission)
    {
    }
    public virtual void DeniedBy(SystemAdmin admin, SystemPermission permission)
    {
    }
    public virtual void GrantedBy(SystemAdmin admin, SystemPermission permission)
    {
    }
}
public class PermissionClaimed : PermissionState
{
    public PermissionClaimed() : base("CLAIMED")
    {
    }
    public override void DeniedBy(SystemAdmin admin, SystemPermission permission)
    {
        if (permission.Admin != admin) return;
        permission.IsGranted = false;
        permission.IsUnixPermissionGranted = false;
        permission.PermissionState = DENIED;
        permission.NotifyUserOfPermissionRequestResult();
    }
    public override void GrantedBy(SystemAdmin admin, SystemPermission permission)
    {
        if (permission.Admin != admin) return;
        
        if (permission.IsUnixPermissionDesiredButNotRequested())
        {
            permission.PermissionState = UNIX_REQUESTED;
            permission.NotifyUserOfPermissionRequestResult();
            return;
        }
        permission.PermissionState = GRANTED;
        permission.IsGranted = true;
        permission.NotifyUserOfPermissionRequestResult();
    }
}
public class PermissionDenied : PermissionState
{
    public PermissionDenied() : base("DENIED")
    {
    }
}
public class PermissionGranted : PermissionState
{
    public PermissionGranted() : base("GRANTED")
    {
    }
}
public class PermissionRequested : PermissionState
{
    public PermissionRequested() : base("REQUESTED")
    {
    }
    public override void ClaimedBy(SystemAdmin admin, SystemPermission permission)
    {
        permission.WillBeHandledBy(admin);
        permission.PermissionState = CLAIMED;
    }
}
public class UnixPermissionClaimed: PermissionState
{
    public UnixPermissionClaimed() : base("UNIX_CLAIMED")
    {
    }
    public override void DeniedBy(SystemAdmin admin, SystemPermission permission)
    {
        if (permission.Admin != admin) return;
        permission.IsGranted = false;
        permission.IsUnixPermissionGranted = false;
        permission.PermissionState = DENIED;
        permission.NotifyUserOfPermissionRequestResult();
    }
    public override void GrantedBy(SystemAdmin admin, SystemPermission permission)
    {
        if (permission.Admin != admin) return;
        if (permission.IsUnixPermissionRequestedAndClaimed())
        {
            permission.IsUnixPermissionGranted = true;
        }
        permission.PermissionState = GRANTED;
        permission.IsGranted = true;
        permission.NotifyUserOfPermissionRequestResult();
    }
}
public class UnixPermissionRequested : PermissionState
{
    public UnixPermissionRequested() : base("UNIX_REQUESTED")
    {
    }
    public override void ClaimedBy(SystemAdmin admin, SystemPermission permission)
    {
        permission.WillBeHandledBy(admin);
        permission.PermissionState = UNIX_CLAIMED;
    }
}
PermissionState實作, 實作的三大函數:ClaimedBy, DeniedBy與GrantedBy
SystemAdmin與SystemPermission兩種物件做判斷, 並在需要時更改這些物件的數值.而SystemPermission重構成:
public class SystemPermission
{
    private SystemAdmin _admin;
    private SystemProfile _profile;
    private SystemUser _requestor;
    public SystemPermission(SystemAdmin admin, SystemUser requestor, SystemProfile profile)
    {
        _admin = admin;
        _requestor = requestor;
        _profile = profile;
        IsGranted = false;
        PermissionState = PermissionState.REQUESTED;
        NotifyAdminOfPermissionRequest();
    }
    public PermissionState PermissionState { get; internal set; }
    public bool IsGranted { get; internal set; }
    public bool IsUnixPermissionGranted { get; internal set; }
    public SystemAdmin Admin => _admin;
    private void NotifyAdminOfPermissionRequest()
    {
    }
    public void ClaimedBy(SystemAdmin admin)
    {
        PermissionState.ClaimedBy(admin, this);
    }
    internal void WillBeHandledBy(SystemAdmin admin)
    {
        _admin = admin;
    }
    public void DeniedBy(SystemAdmin admin)
    {
        PermissionState.DeniedBy(admin, this);
    }
    internal void NotifyUserOfPermissionRequestResult()
    {
    }
    public void GrantedBy(SystemAdmin admin)
    {
        PermissionState.GrantedBy(admin, this);
    }
    internal bool IsUnixPermissionDesiredButNotRequested()
    {
        return _profile.IsUnixPermissionRequired && IsUnixPermissionGranted;
    }
    internal bool IsUnixPermissionRequestedAndClaimed()
    {
        return _profile.IsUnixPermissionRequired && PermissionState == PermissionState.UNIX_CLAIMED;
    }
    internal bool IsClaimedState()
    {
        return PermissionState == PermissionState.CLAIMED || PermissionState == PermissionState.UNIX_CLAIMED;
    }
}
從上述看到, SystemPermission擁有PermissionState物件, 而任何的狀態處理都是委託PermissionState完成.
這項重構手法是 Replace State-Altering Conditionals with State
是一種善用多型的方式重構.
其他還有
Replace Conditional Logic with Strategy
Move Embellishment to Decorator
Introduce Null Object
也都是處理這種smell的重構手法