2017-01-13 2 views
-1

У меня есть требование рефакторинга кода, в котором у меня есть несколько классов, и объект классов должен создаваться динамически в зависимости от пользовательского запроса. Теперь все классы существуют и в них нет общих методов, которые бы соответствовали друг другу. Поэтому я не могу добавить к нему интерфейс и создать фабричный класс, который вернет ссылку на интерфейс, ссылающуюся на фактический класс. Есть ли способ с генериками или любым другим способом реорганизовать это, чтобы динамически создавать объекты. Подход, который мы имеем сейчас, состоит в том, что существует основной класс, в котором объект каждого класса создается и все методы вызываются. Можем ли мы реализовать заводскую модель без интерфейса или любого решения для моего сценария? Пожалуйста.Реализация FactoryPattern без использования интерфейса C#

Добавление образца кода для объяснения сценария.

public interface ITest 
{ 
    string TestMethod1(string st, int ab); 
    int TestMethod2(string st); 
    void TestMethod4(int ab); 
    float ITest.TestMethod3(string st); 
} 
public class Class1 : ITest 
{ 
    public string TestMethod1(string st, int ab) 
    { 
     return string.Empty; 
    } 
    public void TestMethod4(int ab) 
    { 
     throw new NotImplementedException(); 
    } 

    public int TestMethod2(string st) 
    { 
     throw new NotImplementedException(); 
    } 

    public float TestMethod3(string st) 
    { 
     throw new NotImplementedException(); 
    } 
} 
public class Class2 : ITest 
{ 

    float ITest.TestMethod3(string st) 
    { 
     return float.Parse("12.4"); 
    } 

    void ITest.TestMethod4(int ab) 
    { 
     throw new NotImplementedException(); 
    } 
    public string TestMethod1(string st, int ab) 
    { 
     throw new NotImplementedException(); 
    } 

    public int TestMethod2(string st) 
    { 
     throw new NotImplementedException(); 
    } 
} 
public class Main 
{ 
    ITest test = null; 

    public ITest CreateFactory(TestType testType) 
    { 
     switch(testType) 
     { 
      case TestType.Class1: 
       test = new Class1(); 
       break; 
      case TestType.Class2: 
       test = new Class2(); 
       break; 
     } 
     return test; 
    } 
} 

enum TestType 
{ 
    Class1, 
    Class2 
} 

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

Моя идея - использовать что-то вроде приведенного ниже, но не уверен, что тип возвращаемого значения будет или должен быть определен как.

public T CreateFactory(TestType testType) 
    { 
     switch(testType) 
     { 
      case TestType.Class1: 
       return GetInstance<Class1>("Class1"); 

      case TestType.Class2: 
       return GetInstance<Class1>("Class2"); 

     } 
     return null; 
    } 
    public T GetInstance<T>(string type) 
    { 
     return (T)Activator.CreateInstance(Type.GetType(type)); 
    } 

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

Ответ на мою проблему

public static T CreateFactory<T>() 
    where T: IFactory, new() 
{ 
    return new T(); 
} 
+0

создать пост на http://codereview.stackexchange.com или вставить код здесь иначе это только теоретическая дискуссия –

+0

Как вы узнаете позже (после создания объектов), как обращаться или какие методы нужно вызывать? Эта логика может помочь решить вашу проблему. –

+0

моя проблема в этом. У меня есть класс, который создает объекты указанного типа и возвращает созданный объект, однако для его возврата мне нужно отбросить его или преобразовать или иметь интерфейс, который реализуется всеми моими классами, а затем вернуть этот интерфейс ref, но У меня не может быть интерфейса здесь bcoz нет общих методов, так что я могу сделать в этом случае? – Blossom

ответ

1

Я не говорю полностью понять проблему, но дать ему шанс ...

Factory как класс, что у вас есть:

class Factory 
{ 
    public static Visitable Create(string userInput) 
    { 
     switch (userInput) 
     { 
      case nameof(ClassA): 
       return new ClassA(); 
      case nameof(ClassB): 
       return new ClassB(); 
      default: 
       return null; 
     } 
    } 
} 

Типы, которые вы должны создать:

class ClassA : Visitable 
{ 
    public void M1(){} 
    public override void Accept(Visitor visitor){visitor.Visit(this)} 
} 

class ClassB : Visitable 
{ 
    public void M2(){} 
    public override void Accept(Visitor visitor){visitor.Visit(this)} 
} 

Использование кода:

var visitor = new Visitor(); 
var obj = Factory.Create("ClassA"); 
obj.Accept(visitor); 

А недостающие части:

class Visitor 
{ 
    public void Visit(ClassA obj){ obj.M1(); } // Here you have to know what method will be called! 
    public void Visit(ClassB obj){ obj.M2(); } // Here you have to know what method will be called! 
} 

abstract class Visitable 
{ 
    public abstract void Accept(Visitor visitor); 
} 

Это называется паттерн посетитель. Если вы знаете, какие методы нужно называть Visitor.Visit, это то, что вы хотите.

+0

это ново для меня, но я не думаю, что это сработает для меня. Есть много классов, и они продолжают добавляться, поэтому я должен продолжать вносить изменения здесь, если я иду на фабрику, все, что мне нужно, это добавить коммутатор и метод в интерфейс. но спасибо за то, что нашли время, чтобы объяснить это так хорошо. – Blossom

+0

По крайней мере теперь вы знаете, что является правильным способом :) Я не знаю никаких других шаблонов/методов, которые могут вам помочь. Может быть, черная магия ... Это хороший сайт о моделях: http://www.dofactory.com/net/design-patterns Стоит посмотреть! –

+0

Совмещение шаблонов, но это функция C# 7, вам нужно подождать. –

0

Я не совсем понимаю ваш вопрос, но базовое утверждение неверно. Меня интересует ваш дизайн, учитывая основы вашего вопроса.

Несмотря на это, предложил мое решение:

Вы говорите, что у вас нет единого объекта (непрямой, непосредственно вы заявили: «Я не могу иметь интерфейс, потому что никакие общие методы не в этом.»

object является общим элементом.

Я не потворствую этому, но вы можете создать фабричный объект, который только что вернул object в качестве типа данных. Проблема с этим вы затем бросить его после создания объекта, который вы не можете возражаете ...

internal class MyFactory 
{ 
    internal object CreateItem1() { return ...; } 
    internal object CreateItem2() { return ...; } 
    internal object CreateItem2(ExampleEnum e) 
    { 
     switch(e) 
     { 
      case e.Something: 
       return new blah(); 
      default: 
       return new List<string>(); 
     } 
    } 

} 
+0

У меня есть простой шаблон фабрики, не знаю, почему кто-то не в состоянии это понять, мое единственное изменение, которое требуется здесь, - это заменить интерфейс чем-то другим, например родовым, вернуть объект типа T, но я не знаю, как его реализовать. – Blossom

+0

Это мое предложение. Используйте 'object', который является базой для всего объекта внутри CLR (.NET) независимо от объявления (он неявный). В моем случае я не понимаю цели. Если вы не можете предсказать тип объекта, вы не можете правильно проектировать свои объекты. Это очень большая тема, но независимо от причины, мой ответ должен быть адекватным, исходя из того, что вы прокомментировали. –

+0

, но на принимающей стороне, как я узнаю, какой тип будет преобразовывать обратно из объекта, который я отправляю? – Blossom

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