简体   繁体   中英

Factory of plain classes derived from generic specializations

I have a C# generic class B<T> . Also I have a set of derived classes Di : B<Ti> . All that classes are always created with the same set of parameters. So it leads to spagetti code:

if (typeof(T) == typeof(A1)) {work with D1}
else if (typeof(T) == typeof(A2)) {work with D2}
...

Obviously I want to refactor the code in way it'll look like:

var dInst = GiveMeD<T>();
work with Di

How can I implement function GiveMeD<T>() ?

UPDATE:

work with Di -> casting to base class B<T> and work with its interface. The main problem here - each block of code differs in derived class constructor invocation.

If you want to refactor effectively the code this way then you must take into account that "working with D1 " and "working with D2 " must be the same and only the behavior must differ; that is, D1 and D2 must have a common "interface" ( B<T> ) and you should only leverage said "interface", otherwise you will start having spaghetti code all over the place again and ugly casts.

If this fits your needs (if it doesn't then you should reconsider your whole approach to the problem), the common pattern is to simply create a factory method where your spaghetti code will only be written once:

public static B<T> CreateD<T>()
{
    if (T is A1) return ... //here you can create a new instance of D1 or return a cached one, etc.
    else if (T is A2) return ...
}

A beautiful pattern I like to use when the consumer does not need know anything about D1 , D2 , etc. and only needs to know about B<T> is the following:

public class B<T>
{
    public B<T> CreateD<T>()
    {
        if (T is A1) return ... //here you can create a new instance of D1 or return a cached one, etc.
        else if (T is A2) return ...
        ...
    }

    private B() { } //note constructor is private, consumer can't create a B<T>

    private class D1: B<A1> { ... } //private nested types, not visible outside B<T>.
    private class D2: B<A2> { ... }
}

Now you have absolute control on how many Di s can be implemented, you expose one single general purpose B<T> and you guarantee to give back always the correctly specialized type without actually making the consumer have to know anything about it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM