2013-05-09 4 views
0

я работаю в системе, которая использует структуру интерфейса и класса, подобную этой:конструкция для сменного использования легких и полных объектов

interface ILw    // a lightweight interface definition 

class Medium : ILw 

class FullA : Medium   // full class definitions 
class FullB : Medium 

class LwA : ILw    // lightweight class definitions 
class LwB : ILw 

В системе я сталкиваюсь предметами, которые могут быть полностью или легкими, поэтому есть функции, которые ожидают интерфейс ILw. Проблема, с которой я сталкиваюсь с этим дизайном, заключается в том, что есть больше данных и методов, которые должны быть разделены между полной и облегченной версиями объектов, чем определено в ILw. Так что я считаю себя необходимости делать что-то вроде этого:

if (myvar is FullA) 
{ 
    (myvar as FullA).MyFunction() 
} 
else 
{ 
    (myvar as LwA).MyFunction() 
} 

где MyFunction() осуществляется отдельно в каждом Fulla и LwA и может работать на одинаковых структур данных. Я хочу устранить это дублирование кода.

С моим фоном C++ это типичный случай для множественного наследования; то есть определить класс SharedA для данных и методов, которые необходимы и добавить в родительский список FullA и LwA. Но мне нужно руководство, чтобы помочь продумать это в мире C# и интерфейсов. Есть ли принятый шаблон для решения этой проблемы?

спасибо.

UPDATE:

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

public interface ILwBase { } 

class Medium : ILwBase { } 

public class LwDataA 
{ 
    static private int _count = 0; 
    public int id; 
    public LwDataA() { id = ++_count; } 
} 

public interface ILwA : ILwBase 
{ 
    LwDataA ExtData { get; } 
} 

public static class ExtLwA 
{ 
    public static void MyFunction(this ILwA o) 
    { 
     Console.WriteLine("id = " + o.ExtData.id); 
    } 
} 

class LwA : ILwA 
{ 
    private LwDataA _extData = new LwDataA(); 
    public LwDataA ExtData { get { return (_extData); } } 
} 

class FullA : Medium, ILwA 
{ 
    private LwDataA _extData = new LwDataA(); 
    public LwDataA ExtData { get { return (_extData); } } 
} 

class Program 
{ 
    static void Main() 
    { 
     ILwA a1 = new FullA(); 
     ILwA a2 = new LwA(); 

     a1.MyFunction(); 
     a2.MyFunction(); 
    } 
} 

Это позволяет использовать только две строки дублирующего кода между LwA и FullA. И он устраняет необходимость вызова свойства aggregate (мое предыдущее редактирование) или реализации оберток вокруг совокупности.

Надеюсь, это разъясняет, чего я пытаюсь достичь. Это лучшее решение?

+0

Если вам нужно обработать Fulla и LWA по-разному, они могут ** действительно ** можно сказать быть закодированным в один и тот же интерфейс? Может быть, ваш интерфейс нарушен дизайном и должен быть лучше/более полным? – Patashu

+0

@Patashu Много раз мне все равно, работаю ли я с «полным» объектом. То, что мне нужно сделать в этих случаях, - это работа с небольшим подмножеством данных и методов, которые являются общими между ними. – jltrem

+0

Если интерфейс не делает этого для вас (определите все методы, которые являются общими между двумя), ваш интерфейс сломан. – Patashu

ответ

2

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

Вариант 1: Обманите свои специальные классы, которые нуждаются в MyFunction(), чтобы получить его как метод расширения. Для этого вам нужен «дифференциатор»; в моем примере это интерфейс ILwA. Обратите внимание, что он должен определить другую общность, а не MyFunction(). Геттер (или сеттер) будет делать. Ограничение здесь заключается в том, что MyFunction не имеет доступа к закрытым членам.

//instead of the lightweight interface (but use interface if it makes more sense) 
abstract class LwBase 

abstract class HwBase : LwBase 

public interface IADiff { int APropTrick { get; } } 

// lightweight class definitions 
class LwA : LwBase, IADiff 
class LwB : LwBase 

// full class definitions 
class FullA : HwBase, IADiff 
class FullB : HwBase 

public static class AExtensions 
{ 
    public static void MyFunction(this IADiff o) 
    { 
     // impl. 
    } 
} 

Вариант 2: использовать общий класс, который обеспечивает реализацию MyFunction() и «перенаправить» к нему:

abstract class LwBase 

abstract class HwBase : LwBase 

public interface IADiff { int MyFunction(); } 

public class AConcr : IADiff //implemenst Myfunction() 

// lightweight class definitions 
class LwA : LwBase, IADiff 
{ 
    private AConcr a = new AConcr(); 

    public int MyFunction() { return a.MyFunction(); } 
} 
class LwB : LwBase 

// full class definitions 
class FullA : HwBase, IADiff 
{ 
    private AConcr a = new AConcr(); 

    public int MyFunction() { return a.MyFunction(); } 
} 
class FullB : HwBase 

Вариант 3: Я наткнулся на this article как я исследовал свой вопрос. Я не могу быстро сказать, является ли это жизнеспособным вариантом, но он, безусловно, дает идеи.

Кредиты: Я в значительной степени заимствую от this SO thread, а также с использованием this nice site в качестве справки.

+0

где вы определяете MyFunction() в этом? Если я определяю его в абстрактном классе, то я до сих пор не уверен, как решить проблему без множественного наследования из-за класса Intermediate. – jltrem

+0

Вы указываете 'где MyFunction() реализуется отдельно в каждом FullA и LwA', поэтому вы определяете MyFunction в ILwA, и для его реализации требуются как LwA, так и FullA. Я обновил свой ответ. –

+0

да, вот как у меня теперь код ... MyFunction() реализуется идентично в FullA и LwA. Но я стараюсь избавиться от дублирования, если это возможно. – jltrem

1

Для совместного осуществления вы можете иметь их оба наследуют от abstract:

interface ILwBase    // a lightweight interface definition 
interface ILwA : ILwBase 
interface ILwB : ILwBase 

class Intermediate : ILwBase 

abstract class AbstractA : ILwA { 
    void MyFunction() {...} 
} 

class LwA : AbstractA, Intermediate 
class LwB : Intermediate 

class FullA : AbstractA 
class FullB : ILwB 

Подробнее о Abstract Classes (on MSDN)

+0

Абстрактный класс решает проблему совместного использования. Но оставшаяся проблема заключается в использовании класса Intermediate: 'class LwA: AbstractA, Intermediate' не будет компилироваться, потому что это множественное наследование. – jltrem

+0

О, извините, я думал, что 'Intermediate' был также интерфейсом. Моя вина. – CodingWithSpike

+0

Да, начиная с * I * смущает. Должно быть, это называется Middle. – jltrem

Смежные вопросы