Реализовать общее поведение в альтернативе абстрактным базовым классам?

В C# у меня есть иерархия классов с несколькими абстрактными базовыми классами около вершины и достаточного количества производных классов. Несколько этих реальных классов имеют некоторую общую собственность и методы, которые реализованы тождественно. Это кажется мне расточительный и таким образом, одно решение могло бы состоять в том, чтобы реализовать это общее поведение в другом абстрактном базовом классе.

abstract class Control;

abstract class SquareControl: Control
{
    public int SquarishProperty;
    public void SquarishMethod();
};

class Window: SquareControl;
class Button: SquareControl;

Однако, что, если несколько других классов в иерархии совместно использовали некоторое другое поведение, но также и что-то общее доли с одними из средств управления от другого базового класса? Возможно, существует много областей общности. Это стало бы непрактичным для моделирования, это с реализацией абстрактного базового класса не будет он?

abstract class FlashableControl: Control
{
    public int FlashyProperty;
    public void FlashMethod();
};

class StatusBar: FlashableControl;  // but it's also a bit square too, hmm...

Таким образом, как Вы идете о совместном использовании таких реализаций через классы, не используя базовые классы?

Я предполагаю, что хочу делегировать implementaion интерфейса к другому классу и иметь ту реализацию класса те свойства и методы от имени желаемых классов, так, чтобы пользователю, StatusBar и Окно, казалось, поддерживали стандартный интерфейс, но под покрытиями это - что-то еще, что реализует его.

Я могу визуализировать агрегирующиеся классы, которые реализуют это поведение, но действительно ли это является соответствующим и является там какими-либо ловушками? Каковы альтернативы?

Спасибо

7
задан DaBozUK 18 June 2010 в 21:41
поделиться

3 ответа

Вы можете использовать такой шаблон:

public interface ICommonServices
{
    string SomeProperty { get; set; }

    void SomeMethod(string param);
}

public static class CommonServiceMethods
{
    public static void DoSomething(this ICommonServices services, string param)
    {
        services.SomeMethod(services.SomeProperty + ": " + param + " something extra!");
    }
}

Все классы, реализующие ICommonServices, теперь также получают некоторое свободное поведение с помощью метода расширения, который зависит исключительно от тех функций, которые предоставляются всеми разработчиками ICommonServices. Если вам нужен доступ к функциям базового класса, вы можете поместить его в отдельный интерфейс, и ICommonServices также реализует этот интерфейс. Теперь вы можете создавать функциональные возможности расширения «по умолчанию» для интерфейсов без использования нескольких базовых классов.


РЕДАКТИРОВАТЬ

Если вы хотите, чтобы некоторые из этих методов были внутренними, вы можете изменить шаблон следующим образом:

public class MyObject : IServices
{
    public string PublicProperty { get; private set; }

    string IServices.SomeProperty { get; set; }

    void IServices.SomeMethod(string param)
    {
        //Do something...
    }
}

public interface IPublicServices
{
    string PublicProperty { get; }
}

internal interface IServices : IPublicServices
{
    string SomeProperty { get; set; }

    void SomeMethod(string param);
}

internal static class ServiceMethods
{
    public static void DoSomething(this IServices services, string param)
    {
        services.SomeMethod(services.SomeProperty + ": " + param + " something extra!");
    }
}

В основном мы раскрываем как общедоступные, так и внутренние интерфейсы. Обратите внимание, что мы реализуем методы внутреннего интерфейса явно, поэтому методы не доступны для публичного использования (поскольку публичный клиент не может получить доступ к типу интерфейса). В этом случае вспомогательные методы расширения являются внутренними, полагаясь на внутренний интерфейс, хотя вы также можете создать общедоступные вспомогательные методы, которые полагаются на общедоступный интерфейс.

3
ответ дан 7 December 2019 в 09:56
поделиться

Один из способов - использовать интерфейсы и базовые классы.

Flashable может создать хороший интерфейс вместо класса.

0
ответ дан 7 December 2019 в 09:56
поделиться

Вы можете использовать «has-a» вместо «is-a» и делегировать внутренний квадратный элемент управления

    class Window : Control, ISquareControl
    {
        private SquareControl square;

        public void SquareOperation()
        {
            square.SquareOperation();
        }
    }

    class SquareControl : Control, ISquareControl
    {
        public void SquareOperation()
        {
            // ...
        }
    }
3
ответ дан 7 December 2019 в 09:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: