Заменить наследование композицией в обобщенных c классах? - PullRequest
1 голос
/ 04 марта 2020

Я много читал о композиции и пытался понять, как я могу реорганизовать свое дерево наследования, используя композицию. В настоящее время мой класс выглядит следующим образом:

public abstract class BaseClass
{
    public abstract string displayText { get; }

    public abstract List<Parameter> parameters { get; }

    public abstract void FireEvent();
}

public abstract class SubClass<T> : BaseClass
{
    private string _displayText;
    public override string displayText { get { return _displayText; } }

    private List<Parameter> _parameters;
    public override List<Parameter> parameters { get { return _parameters; } }

    private T _value;    // ADDED TO SUBCLASS
    public abstract Event<T> Evt { get; } // ADDED TO SUBCLASS

    public override void FireEvent()
    {
        Evt.Raise(_value);
    }
}

public class IntClass : SubClass<int>{}
public class StringClass : SubClass<string>{} // more subclasses like this

Насколько я понимаю, здесь происходит наследование и композиция.

Подкласс Has-A : (Композиция)

  1. Список Parameters
  2. Поле для Event
  3. Поведение Event<T>, которое вызывается в его собственном FireEvent методе

Подкласс Is-A : Базовый класс (Наследование)

IntClass / StringClass Is-A : Подкласс & BaseClass

Причина для создания BaseClass, потому что мне нужны полиморфные c списки. Таким образом, я могу создать List<BaseClass> и вызвать FireEvent() для каждого элемента в списке и получить доступ к displayText и List<Parameter> в al oop.

В будущем мне понадобится подпрограмма класс, который не имеет Event и подкласс, который будет принимать параметр в FireEvent(). Другие варианты могут появиться.

Как бы я полностью заменил мою текущую структуру на композиционный подход? Это вообще выполнимо?

1 Ответ

1 голос
/ 04 марта 2020

В этом примере у вас есть 3 поведения. Int использует 3, String использует только 2. Если вы помещаете код таким образом, когда вы меняете AnotherServiceB, вам не нужно беспокоиться о том, что он ломает String (поскольку String не имеет этой службы)

public class FireEventService<T>
{
    private T _value;    // ADDED TO SUBCLASS
    public abstract Event<T> Evt { get; } // ADDED TO SUBCLASS

    public override void FireEvent()
    {
        Evt.Raise(_value);
    }
}

public class AnotherService
{

}

public class AnotherServiceB
{

}

public abstract class SubClass<T> : BaseClass
{
    private readonly FireEventService<T> _fireEventService;
    private readonly AnotherService _anotherService;

    private string _displayText;
    public override string displayText { get { return _displayText; } }

    private List<Parameter> _parameters;
    public override List<Parameter> parameters { get { return _parameters; } }

    public SubClass(FireEventService<T> fireEventService, AnotherService anotherService)
    {
        // All those services should use with interface and Dependency Injection
        _fireEventService = fireEventService;
        _anotherService = anotherService;
    }

    public void FireEvent() => _fireEventService.FireEvent();
}

public class IntClass : SubClass<int>
{
    private readonly AnotherServiceB _anotherServiceB;
    public IntClass(FireEventService<int> fireEventService, AnotherService anotherService, AnotherServiceB anotherServiceB)
        : base(fireEventService, anotherService)
    { }
    public void DoSomethingUsingServiceB()
    {
        //_anotherServiceB.DoSomething();
    }
}
public class StringClass : SubClass<string> 
{
    public StringClass(FireEventService<string> fireEventService, AnotherService anotherService)
        : base(fireEventService, anotherService)
    { }
}
...