Design template for removing multiple if / else options with related objects

I have inherited the following (terrible) code and am wondering how best to reorganize it.

There are large if / else clauses throughout the codebase, one of which is similar to the one below:

public class BaseResultItem
{
    public int Property1 { get; set; }
}

public class ResultItem1 : BaseResultItem
{
    public int Property2 { get; set; }
}

public class ResultItem2 : BaseResultItem
{
    public int Property3 { get; set; }
}

public class BaseHistoryItem
{
    public int Property1 { get; set; }
}

public class HistoryItem1 : BaseHistoryItem
{
    public int Property2 { get; set; }
}

public class HistoryItem2 : BaseHistoryItem
{
    public int Property3 { get; set; }
}

public class HistoryBuilder
{
    public BaseHistoryItem BuildHistory(BaseResultItem result)
    {
        BaseHistoryItem history = new BaseHistoryItem            
        {
            Property1 = result.Property1
        };

        if (result is ResultItem1)
        {
            ((HistoryItem1)history).Property2 = ((ResultItem1)result).Property2;
        }
        else if (result is ResultItem2)
        {
            ((HistoryItem2)history).Property3 = ((ResultItem2)result).Property3;
        }

        return history;
    }
}

Note that this is a simplified example, and there are many more classes in the actual code. All places have similar if / else conditions.

I am considering an abstract factory pattern, but I am having some problems.

Basically, I assume that in order to avoid if / else problems, I need to pass the actual hidden types. Therefore, should BuildHistory not use base types and maybe there should be several methods, one per derived type?

+3
3

DTO, , HistoryBuilder . HistoryBuilderX HistoryItem ResultItem. , HistoryBuilderX ResultItem.

, BaseResultItem, GetBuilder, if..else if.. construct, ResultItems.

, ResultItem HistoryBuilderX. .

+1

" " - . : BuildHistory BaseResultItem, .

, , ( ). - , .

+1

, .

if (result is ResultItem1)
{
    ((HistoryItem1)history).Property2 = ((ResultItem1)result).Property2;
}

-

result.addToHistory( history );

- , . - :

public class Visitor {
     History history;
     public visit ( ResultItem1 item )  { ... }
     public visit ( ResultItem2 item )  { ... }
     ...
}

public class ResultItem1 {
     public accept( Visitor v ) { v.visit( this ); }
}

typecheck , .

, . , .

0

Source: https://habr.com/ru/post/1733338/


All Articles