Many if statements - refactoring
Personally, I wouldn't use that approach, because of the amount of boilerplate code and complexity it introduces. Adding N+1 classes, where N is the number of conditions, just seems like overkill to me.

First off, I don't think that the method at hand must necessarily be refactored. I agree that is not a terribly "nice" method from a aesthetic point of view, but the amount of complexity it contains might not justify a refactor. Often, a bit of reformatting is already a good approach:

public int inferCategoryID(Component c) {
    if( c.hasOneChannel() &amp;&amp;
        c.hasValidCertificate() &amp;&amp;
        c.isTested() &amp;&amp;
        c.frequentlyUsed()) {
        return 24;
    }

    [...]
}


If that is not satisfactory, my next approach would've been to simply used separate methods for the conditions. This doesn't imply creating lots of classes, but still clean up the inferCategoryID substantially. While I'm not a fan of giving names like isCat24, I will use it here since the example refactoring technique using classes does so too and I can't infer more useful naming from the conditions:

public int inferCategoryID(Component c) {
    if(isCat24(c)) {
        return 24;
    }

    [...]
}

public boolean isCat24(Component c) {
    return c.hasOneChannel() &amp;&amp;
           c.hasValidCertificate() &amp;&amp;
           c.isTested() &amp;&amp;
           c.frequentlyUsed();
}


Last but not least, in cases where lots of boolean conditions are used, bit-lists are often applicable. The following code isn't tested, but it should give an idea of what I mean:

const int CATEGORY_24 = 15;
const int CATEGORY_95 = 13;

public int inferCategoryID(Component c) {
    int properties = componentProperties(c);

    if(properties == CATEGORY_24) {
        return 24;
    }

    if(properties == CATEGORY_95) {
        return 95;
    }

    [...]
}

public int componentProperties(Component c) {
    return ((int) c.hasOneChannel() &lt;&lt; 3) &amp;&amp;
           ((int) c.hasValidCertificate() &lt;&lt; 2) &amp;&amp;
           ((int) c.isTested() &lt;&lt; 1) &amp;&amp;
           ((int) c.frequentlyUsed());
}


The integer returned from componentProperties is a dense representation of the components properties in form of a bit list, that is each bit represents one boolean property. For example, if all properties are true, the resulting integer (in binary) would be 1111, if only hasOneChannel was true, the integer would be 1000 and so on. This has the advantage that you don't have to create a large amount of methods or classes, but still cleans up the inferCategoryID method quite nicely. The downside of this method is that it is arguably the most cryptic (while I also find the multiple-class approach relatively cryptic :D).

Since I said that adding lots of classes introduces too much complexity to be really worth it (in this case), I can't say that the last solution is any different in terms of adding unnecessary complexity, so I probably wouldn't use either of them for the use case at hand. I just wanted to give you an idea of a different approach that, in my opinion, is preferable to creating a class per condition :)