Generic base class wraps nested generic class to reduce type argument specification: Is there a name for this pattern?
Asked Answered
T

3

1

Ok question title is far from being self-explanatory. I see myself doing this often:

From this answer:

public static class Equality<T>
{
    public static IEqualityComparer<T> CreateComparer<K>(Func<T, K> keySelector)
    {
        return new KeyEqualityComparer<K>(keySelector);
    }



    class KeyEqualityComparer<K> : IEqualityComparer<T>
    {
        readonly Func<T, K> keySelector;

        public KeyEqualityComparer(Func<T, K> keySelector)
        {    
            this.keySelector = keySelector;
        }

        public bool Equals(T x, T y)
        {
            ----
        }

        public int GetHashCode(T obj)
        {
            ....
        }
    }
}

What did I do: There is an implementation detail KeyEqualityComparer<T, K> which I had to call:

new KeyEqualityComparer<Person, int>(p => p.ID);

By nesting it as a private class, not only did I hide the implementation (the public constructor of internal class is obscure now), but got a better syntax:

Equality<Person>.CreateComparer(p => p.ID);

Note here that I haven't inherited nested class from the parent class (which is static).

Or sometimes I see myself doing this:

public abstract class Equater<T> : IEqualityComparer<T>
{
    public static Equater<T> Create<TKey>(Func<T, TKey> keySelector)
    {
        return new Impl<TKey>(keySelector);
    }

    public abstract bool Equals(T x, T y);

    public abstract int GetHashCode(T obj);



    class Impl<TKey> : Equater<T>
    {
        readonly Func<T, TKey> keySelector;

        public Impl(Func<T, TKey> keySelector)
        {
            this.keySelector = keySelector;
        }

        public override bool Equals(T x, T y)
        {
            ----
        }

        public override int GetHashCode(T obj)
        {
            ....
        }
    }
}

Another similar one here

public class Accessor<S>
{
    public static Accessor<S, T> Create<T>(Expression<Func<S, T>> memberSelector)
    {
        return new GetterSetter<T>(memberSelector);
    }

    class GetterSetter<T> : Accessor<S, T>
    {
        public GetterSetter(Expression<Func<S, T>> memberSelector) : base(memberSelector)
        {

        }
    }
}

public class Accessor<S, T> : Accessor<S>
{
    Func<S, T> Getter;
    Action<S, T> Setter;

    public bool IsReadable { get; private set; }
    public bool IsWritable { get; private set; }
    public T this[S instance]
    {
        get
        {
            if (!IsReadable)
                throw new ArgumentException("Property get method not found.");

            return Getter(instance);
        }
        set
        {
            if (!IsWritable)
                throw new ArgumentException("Property set method not found.");

            Setter(instance, value);
        }
    }

    protected Accessor(Expression<Func<S, T>> memberSelector) //access not given to outside world
    {
        ----
    }

}

Note that in these two cases I inherited from wrapping class. So now not only did I get the benefits of the former but I can also maintain a list like this:

List<Equater<Person>> { persons with different implementations };

Its helping me from time to time. So I'm curious to know if there is a name for this pattern?

Thanksgiving answered 18/4, 2013 at 11:57 Comment(0)
T
0

As rightly pointed out by Bertie, I might have not followed any one pattern here.

I would say that by delegating the instantiation of concrete implementation to CreateComparer method, I have just simplified the object creation - which comes under Creation Method patterns. By having a static function for object instantiation, it was sort of a factory pattern - specifically this variant of Factory Method.

By inheriting Impl from Equater I have sort of followed the Abstract Factory pattern - where Equater is factory of factory and Impl is its implementation to give Impl itself back, except that Impl is really not creating any other object (in other words Impl is not meant to be a factory), but getting instantiated itself via constructor. So in strict sense, its not Abstract Factory pattern, but it will be closer to if Impl can have a method to call the constructor of itself and return back an instance.

Also by embedding and hiding the implementation detail (the nested classes as such), the exposed class (parent class) fakes to outside world as if it is doing it's job. It's what is called Delegation Pattern

As far as a name for hiding implementation of a generic class in a nested generic class to give easier signature for method calls is concerned I don't think there exist one. Even if any name existed, it has to be very specific to the language (or similar languages) since language constructs like generics/type inference etc are involved. Eric Lippert finds the same use in nested classes here although its not generics related, where he calls it Factory pattern.

Thanksgiving answered 19/4, 2013 at 9:15 Comment(0)
E
2

I think this is a lot like Class Clusters pattern which is based on Abstract Factory pattern.

Ealing answered 31/10, 2013 at 8:16 Comment(0)
P
1

I don't think you've followed any one pattern here.

I would say that by replacing multiple "CreateComparer" methods with a single "Create" method, you have just simplified a Creation Method pattern. You could in a sense say it was a sort of a Factory pattern?! Or maybe a Builder pattern - that one is open to interpretation I guess?!

By embedding "Impl" within "Equater" you have sort of followed the Command pattern - encapsulating method invocation so that your calling code doesn't know about how it's getting done.

Anyway, sorry I can't be more helpful than that or give you a definite answer! Anyway, hope it helps!

Precipitation answered 18/4, 2013 at 12:42 Comment(7)
Sorry I edited the answer since I think I have not used command or builder pattern at all. Feel free to edit if there are discrepancies in my answerThanksgiving
@nawfal: While we encourage editing answers to improve them, please keep in mind that you should respect the original author's writing in doing so. Your edit seems to change far too much in Bertie's original answer - in particular your edit to the last paragraph can potentially come across as putting words in someone else's mouth. That said, I'll leave it up to Bertie to decide if he wants to keep the edits, or roll them back, as the answer belongs to him. If he does roll them back, you may want to post your research as its own answer.Orcus
Thanks BoltClock - I've rolled back the change as I do believe it changed my original answer far too much. However, if @Thanksgiving would liek to add his comments as a new answer then I obviously have no problem with that.Precipitation
@Orcus sorry, I wanted his answer to be chosen since he gave me the right direction. But I found some factual errors I believe. Though I tried to correct his answer, I left his words as such (thats why you see many similarities) wherever possible. But in the end I agree it was too much edit. Thanks for the tip, I will keep in mind.Thanksgiving
@Precipitation do you really think there is a command pattern or builder pattern here? No way. Command pattern is about encapsulating (as in clubbing together the all the relevant infos) but not in the way I approached (protecting from outside world). In fact I think I'm doing exactly opposite of command pattern where I don't expose the implementation at all but merely the ICommand. See this en.wikipedia.org/wiki/Command_patternThanksgiving
Without getting into a war of words here, yes I do. In terms of patterns - the Command pattern is about delegating method execution and obscuring specific method signatures - which is sort of what you have done - Equater = Command, Impl = Receiver. However, you are right that it also matches the Delegation Pattern. Equally, you could say it looks like a Facade Pattern! Either way, glad I put you onto the right path!Precipitation
@Precipitation sorry if I am annoying you, but I see no evidence for that. And no, no war of words, I'm just trying to learn and give back. If Equater is Command where is the concrete command instance? If it is already concrete, where is ICommand? If Impl is Receiver, how can Receiver be called from Client? Here Receiver (Impl) is already hidden. Where is the invoker which is been delegated the role of invoking the action (execute) later?Thanksgiving
T
0

As rightly pointed out by Bertie, I might have not followed any one pattern here.

I would say that by delegating the instantiation of concrete implementation to CreateComparer method, I have just simplified the object creation - which comes under Creation Method patterns. By having a static function for object instantiation, it was sort of a factory pattern - specifically this variant of Factory Method.

By inheriting Impl from Equater I have sort of followed the Abstract Factory pattern - where Equater is factory of factory and Impl is its implementation to give Impl itself back, except that Impl is really not creating any other object (in other words Impl is not meant to be a factory), but getting instantiated itself via constructor. So in strict sense, its not Abstract Factory pattern, but it will be closer to if Impl can have a method to call the constructor of itself and return back an instance.

Also by embedding and hiding the implementation detail (the nested classes as such), the exposed class (parent class) fakes to outside world as if it is doing it's job. It's what is called Delegation Pattern

As far as a name for hiding implementation of a generic class in a nested generic class to give easier signature for method calls is concerned I don't think there exist one. Even if any name existed, it has to be very specific to the language (or similar languages) since language constructs like generics/type inference etc are involved. Eric Lippert finds the same use in nested classes here although its not generics related, where he calls it Factory pattern.

Thanksgiving answered 19/4, 2013 at 9:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.