Что вы думаете об этом прикован производителя/потребителя/адаптер (шаблон?)


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

Когда я придумал эту, казалось романе наложения продюсер на связанный список - отражение в методе add () - это самое интересное для меня, так как новый адаптер поддерживается через дополнительный конструктор в производном классе.

Концепция повторного использования, что со временем, если мне нужно размещать любые произвольные модели данных в очереди производителя:

  1. добавить код клиента: звоните производитель.Добавить(AnySource) в клиента
  2. создать класс адаптера для вызова typeof(AnySource) в Т
  3. добавить конструктор: DerivedProdcuer(AnySource) - перечислитель инит

Пару вещей мне кажутся интересными и надеялся услышать отзывы о - их оригинальные идеи для меня (конечно, неоригинальный другим).

  • использование отражения в базовый класс, который использует полиморфизм "это"
  • сочетание фабричный метод и метод сбора данных - Добавить(объект) создает новый экземпляр продюсер и добавляет, что экземпляр на связанный список, который в настоящее время за хвост.
void Main()
{
    Producer<Foo> producer = new EntityProducer<Foo>();

    var fooConsumer = new Consumer<Foo>();
    fooConsumer.ItemReady += (sender, item) =>
    {
        Console.Write(item.Data);  
    };

    var modelA = new ModelA();
    modelA.Foos.Add(new Foo { Data = 1 });
    modelA.Foos.Add(new Foo { Data = 2 });
    modelA.Foos.Add(new Foo { Data = 3 }); 
    producer = producer.Add(modelA);    

    var modelB = new ModelB();
    modelB.Bars.Add(new Bar { Data = "4" });
    modelB.Bars.Add(new Bar { Data = "5" });
    modelB.Bars.Add(new Bar { Data = "6" });
    producer = producer.Add(modelB);

    fooConsumer.Consume(producer);
}

class Producer<T>
{
    protected IEnumerator<T> _enum;

    Producer<T> _parent;

    public Producer<T> Add(object obj)
    {
        Producer<T> res = null;
        var constructor = this.GetType().GetConstructor(new [] {obj.GetType()});
        res = (Producer<T>)constructor.Invoke(new [] {obj});       
        res._parent = this;
        return res;
    }

    public IEnumerable<T> Items
    {
        get 
        {
            if(_parent != null && _parent._enum != null)
                foreach (var foo in _parent.Items)
                    yield return foo;

            if(this._enum != null)
                foreach (var foo in Produce(this._enum))
                    yield return foo;
        }
    }

    IEnumerable<T> Produce(IEnumerator target)
    {
        while(target.MoveNext())
        {
            yield return (T)target.Current;
        }
    }
}

class EntityProducer<Foo> : Producer<Foo>
{
    public EntityProducer() { }

    public EntityProducer(ModelA modelA)
    {
        _enum = modelA.Foos.Cast<Foo>().GetEnumerator();
    }

    public EntityProducer(ModelB modelB)
    {
        _enum = new FooAdapter(modelB).Foos.Cast<Foo>().GetEnumerator();
    }
}

class Consumer<T>
{
    public delegate void ItemReadyHandler(Consumer<T> sender, T item);

    public event ItemReadyHandler ItemReady;

    void OnItemReady(T item)
    {
        if(ItemReady != null)
        {
            ItemReady(this, item);
        }
    }

    public void Consume(Producer<T> producer)
    {
        foreach (T item in producer.Items) 
        {   
            OnItemReady(item);
        }
    }
}

class Model
{ 
}

class Entity
{
}

class ModelA : Model
{
    public List<Foo> Foos { get { return _foos; } }
    readonly List<Foo> _foos = new List<Foo>();
}

class Foo : Entity
{
    public int Data { get; set; }
}

class ModelB : Model
{
    public List<Bar> Bars { get { return _bars; } }
    readonly List<Bar> _bars = new List<Bar>();
}

class Bar : Entity 
{
    public string Data { get; set; }
}

class FooAdapter 
{
    readonly ModelB _modelB;

    public FooAdapter(ModelB modelB)
    {
        _modelB = modelB;
    }

    public IEnumerable<Foo> Foos 
    {
        get
        { 
            foreach (var bar in _modelB.Bars) 
            {
                int converted;

                if(!int.TryParse(bar.Data, out converted))
                    throw new Exception("Conversion error while adapting Bar to Foo");

                yield return new Foo { Data = converted };
            }
        }
    }
}


774
5
задан 7 октября 2011 в 07:10 Источник Поделиться
Комментарии
1 ответ

Я думаю, что вы имеете четкого понимания того, что шаблоны проектирования.

Шаблоны идеи (шаблон проектирования) или код (шаблон кода) доказала свою эффективность и принята для использования и проверенной на практике поведения.

Если это метод, чем у вас очень странное видение того, каким методом add выглядит так:

public Producer<T> Add(object obj) 
{
//...
}

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

Затем, вы создали слишком много, слишком сложны и чрезмерного количества классов.

Вот код после рефакторинга дизайна, реализации ваших Дизайн/Шаблон код:

public interface IEntity { }
public interface IEntity<T> : IEntity { T Data { get; set; } }

class Entity<T> : IEntity<T>
{
public T Data { get; set; }
}

class Program
{
static void Main(string[] args)
{
List<IEntity> items = new List<IEntity>();
items.Add(new Entity<int> { Data = 1 });
items.Add(new Entity<int> { Data = 2 });
items.Add(new Entity<int> { Data = 3 });
items.Add(new Entity<string> { Data = "4" });
items.Add(new Entity<string> { Data = "5" });
items.Add(new Entity<string> { Data = "6" });
items.ForEach((item) =>
{
IEntity<string> str = item as IEntity<string>;
if (str != null)
{
Console.Write(str.Data);
}
IEntity<int> val = item as IEntity<int>;
if (val != null)
{
Console.Write(val.Data);
}
});
}
}

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

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

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

Код, который вы создали, кажется, не имеют доказанной эффективности, безопасности и простоте использования, поэтому он не может быть назван картиной. На большинство я могу назвать свой код ошибочный и простая реализация продюсер/узор потребителей, перегружен дженерики и вызов кода через рефлексию.

Окончательный код будет очень простой и понятной:

public interface IEntity { } 
public interface IEntity<T> : IEntity { T Data { get; set; } }
public class Entity<T> : IEntity<T>
{
public T Data { get; set; }
}

4
ответ дан 8 октября 2011 в 04:10 Источник Поделиться