0

Довольно полный рот, но его принцип OO, с которым я боролся. Допустим, у меня есть приложение для электронной коммерции, и есть концепция способа оплаты, примерами могут быть кредитная карта, Paypal, Apple и т. Д. У пользователя есть выбор того, какой метод оплаты выбрать, поэтому мне нужно представить их все в списке на экране и в зависимости от выбора это будет использоваться для управления пользовательским интерфейсом, представляя разные тексты/изображения/взаимодействия, а также будет несколько раз сериализоваться в запросе платежа по проводу.Использование интерфейса/Наследование как маркер, когда конкретный тип представляет собой разные варианты, из которых может быть только один

Вот код:

public class PaypalPayment : PaymentMethod { 

    public string Token; 
    public string String; 

} 

public class CreditCardPayment : PaymentMethod { 

    public Address Address; 
    public CreditCard CreditCard; 

} 

interface PaymentMethod { 

} 


public class Booking { 
    public PaymentMethod PaymentMethod; //generic object 

    //or 

    public PaypalPayment PaypalPayment; 
    public CreditCardPayment CreditCardPayment; 
} 

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

В теории я мог бы добавить некоторые методы в интерфейс PaymentMethod, такие как Serialise() или некоторые методы представления пользовательского интерфейса, которые имеют все способы оплаты, но тогда мне придется реализовать их в моем объекте модели, t хочу сделать в моем модельном слое.

В целом у меня нет чистого решения для этого на вашем типичном ориентированном на объект языке. Я написал это в C#, но это может относиться к любому языку OO.

ответ

0

Чтобы иметь интерфейс и не может получить доступ к базовому типу, это то, к чему стремится абстракция и свободная связь. Это не должно сосать, но должно быть желательно. Чтобы получить все возможные экземпляры на выбор, вы можете использовать репозиторий, который возвращает коллекцию всех ваших способов оплаты. Чтобы реализовать этот репозиторий, вы можете использовать свою привилегированную ORM и загрузить их из базы данных, использовать свой одобренный контейнер IoC/DI и позволить ему создавать всех разработчиков вашего интерфейса или создавать жесткий код для создания. Все, что вам подходит, и потребности проекта. Если вы также используете интерфейс для репозитория, вы можете впоследствии заменить его.

+0

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

+0

@ LukeDeFeo Интерфейс должен включать только самый низкий общий знаменатель между способами оплаты. Если обязанности четко определены, «Бронирование» будет использовать только этот самый низкий общий знаменатель. – guillaume31

+0

@ LukeDeFeo, возможно, вы захотите обновить свой вопрос, заполнив пробел в «PaymentMethod» с помощью операций, которые вы планируете предоставлять. Сейчас кажется, что 'PaymentMethods' являются немыми структурами данных без поведения. – guillaume31

1

Данные, кажется, были отделены от логики в вашем дизайне. Как следствие, Booking, вероятно, должен заниматься Inappropriate Intimacy с его Payment, чтобы поведение происходило, следовательно, проблема кастинга.

Идиоматическая реализация ОО должна 1/определить четкую ответственность и 2/инкапсулировать операции и данные для него в том же классе. Затем вы можете иметь абстракцию поверх семейства этих классов, чтобы их поведение можно было единообразно называть потребительским кодом.

Strategy aka шаблон политики может быть хорошим выбором для оплаты.

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