Builder design pattern with inheritance: is there a better way?

后端 未结 3 1615
失恋的感觉
失恋的感觉 2020-12-24 07:42

I\'m creating a series of builders to clean up the syntax which creates domain classes for my mocks as part of improving our overall unit tests. My builders essentially pop

相关标签:
3条回答
  • 2020-12-24 08:20

    This is a good implementation strategy for C#.

    Some other languages (can't think of name of research language I've seen this in) have type systems that either support a covariant "self"/"this" directly, or have other clever ways to express this pattern, but with C#'s type system, this is a good (only?) solution.

    0 讨论(0)
  • 2020-12-24 08:27

    All I can say is that if there is a way of doing it, I want to know about it too - I use exactly this pattern in my Protocol Buffers port. In fact, I'm glad to see that someone else has resorted to it - it means we're at least somewhat likely to be right!

    0 讨论(0)
  • 2020-12-24 08:32

    I know this is an old question, but I think you can use a simple cast to avoid the abstract BLDR This { get; }

    The resulting code would then be:

    public abstract class BaseBuilder<T, BLDR> where BLDR : BaseBuilder<T, BLDR>
                                               where T : new()
    {
        public abstract T Build();
    
        protected int Id { get; private set; }
    
        public BLDR WithId(int id)
        {
            _id = id;
            return (BLDR)this;
        }
    }
    
    public class ScheduleIntervalBuilder :
        BaseBuilder<ScheduleInterval,ScheduleIntervalBuilder>
    {
        private int _scheduleId;
        // ...
    
        public override ScheduleInterval Build()
        {
            return new ScheduleInterval
            {
                    Id = base.Id,
                    ScheduleId = _scheduleId
                        // ...
            };
        }
    
        public ScheduleIntervalBuilder WithScheduleId(int scheduleId)
        {
            _scheduleId = scheduleId;
            return this;
        }
    
        // ...
    }
    

    Of course you could encapsulate the builder with

    protected BLDR This
    {
        get
        {
            return (BLDR)this;
        }
    }
    
    0 讨论(0)
提交回复
热议问题