Как называется эта модель? - PullRequest
3 голосов
/ 27 октября 2010

Как называется этот шаблон, когда вы даете объекту параметр в его конструкторе, и объект заполняет его поля параметром?

Например:

/// <summary>
/// Represents a user on the Dream.In.Code website.
/// </summary>
public class User
{       
    /// <summary>
    /// Load a user by providing an ID.
    /// </summary>
    /// <param name="ID">A user's individual ID number.</param>
    public User(string ID)
    {
        WebClient webClient = new WebClient();
        string htmlSource = webClient.DownloadString(new Uri(String.Format("http://www.dreamincode.net/forums/xml.php?showuser={0}",ID)));
        XDocument xml = XDocument.Parse(htmlSource);

        var profileXML = xml.Element("ipb").Element("profile");

        //Load general profile information.
        this.ID = profileXML.Element("id").Value;
        this.Name = profileXML.Element("name").Value;
        this.Rating = profileXML.Element("rating").Value;
        this.Photo = profileXML.Element("photo").Value;
        this.Reputation = profileXML.Element("reputation").Value;
        this.Group = profileXML.Element("group").Element("span").Value;
        this.Posts = profileXML.Element("posts").Value;
        this.PostsPerDay = profileXML.Element("postsperday").Value;
        this.JoinDate = profileXML.Element("joined").Value;
        this.ProfileViews = profileXML.Element("views").Value;
        this.LastActive = profileXML.Element("lastactive").Value;
        this.Location = profileXML.Element("location").Value;
        this.Title = profileXML.Element("title").Value;
        this.Age = profileXML.Element("age").Value;
        this.Birthday = profileXML.Element("birthday").Value;
        this.Gender = profileXML.Element("gender").Element("gender").Element("value").Value;

        //Load contact information.
        var contactXML = xml.Element("ipb").Element("profile").Element("contactinformation");
        this.AIM = contactXML.XPathSelectElement("contact[title='AIM']/value").Value;
        this.MSN = contactXML.XPathSelectElement("contact[title='MSN']/value").Value;
        this.Website = contactXML.XPathSelectElement("contact[title='Website URL']/value").Value;
        this.ICQ = contactXML.XPathSelectElement("contact[title='ICQ']/value").Value;
        this.Yahoo = contactXML.XPathSelectElement("contact[title='Yahoo']/value").Value;
        this.Jabber = contactXML.XPathSelectElement("contact[title='Jabber']/value").Value;
        this.Skype = contactXML.XPathSelectElement("contact[title='Skype']/value").Value;
        this.LinkedIn = contactXML.XPathSelectElement("contact[title='LinkedIn']/value").Value;
        this.Facebook = contactXML.XPathSelectElement("contact[title='Facebook']/value").Value;
        this.Twitter = contactXML.XPathSelectElement("contact[title='Twitter']/value").Value;
        this.XFire = contactXML.XPathSelectElement("contact[title='Xfire']/value").Value;

        //Load latest visitors.
        var visitorXML = xml.Element("ipb").Element("profile").Element("latestvisitors");
        this.Visitors = (from visitor in visitorXML.Descendants("user")
                        select new Visitor(){
                            ID = visitor.Element("id").Value,
                            Name = visitor.Element("name").Value,
                            Url = visitor.Element("url").Value,
                            Photo = visitor.Element("photo").Value,
                            Visited = visitor.Element("visited").Value,
                        }).ToList();

        //Load friends.
        var friendsXML = xml.Element("ipb").Element("profile").Element("friends");
        this.Friends = (from friend in friendsXML.Descendants("user")
                        select new Friend()
                        {
                            ID = friend.Element("id").Value,
                            Name = friend.Element("name").Value,
                            Url = friend.Element("url").Value,
                            Photo = friend.Element("photo").Value
                        }).ToList();

        //Load comments.
        var commentsXML = xml.Element("ipb").Element("profile").Element("comments");
        this.Comments = (from comment in commentsXML.Descendants("comment")
                            select new Comment()
                            {
                                ID = comment.Element("id").Value,
                                Text = comment.Element("text").Value,
                                Date = comment.Element("date").Value,
                                UserWhoPosted = new Friend()
                                {
                                    ID = comment.Element("user").Element("id").Value,
                                    Name = comment.Element("user").Element("name").Value,
                                    Url = comment.Element("user").Element("url").Value,
                                    Photo = comment.Element("user").Element("photo").Value
                                }
                            }).ToList();
    } 
}

Что бы этошаблон будет называться?Также, чтобы сделать мой код чище, вы рекомендуете использовать этот шаблон при создании объектов внутри объектов, как в моей переменной UserWhoPosted.Вместо:

UserWhoPosted = new Friend()
{
    ID = comment.Element("user").Element("id").Value,
    Name = comment.Element("user").Element("name").Value,
    Url = comment.Element("user").Element("url").Value,
    Photo = comment.Element("user").Element("photo").Value
}

я бы получил:

UserWhoPosted = new Friend(myFriendXElementVariable);

И просто позвольте ему разобрать, что ему нужно, и заполните его поля.

Спасибо за руководство.

РЕДАКТИРОВАТЬ: После прочтения всех ваших предложений я немного очистил код.Как вы думаете, это лучше?Что бы вы улучшили?

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

http://pastebin.com/AykLjF2i

Ответы [ 7 ]

8 голосов
/ 27 октября 2010

Для меня это скорее анти-шаблон: вы включаете запрос xml, чтение и инициализацию полей в своем конструкторе. Может быть, вы могли бы использовать шаблон Factory с таким:

public static class FactoryUser{
public static User GetUserFromXml(Xml){
//your code here
}
}

public static class UserWebrequester{
public static Xml GetXmlUser(id){
}
}

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

2 голосов
/ 27 октября 2010

Это определенно является нарушением Закона Деметры :

D = comment.Element("user").Element("id").Value,

Вы действительно не хотите иметь такую ​​длинную цепочку вызовов методов.Заставить друга спрашивать значения из его аргумента - это гораздо лучший дизайн с гораздо меньшей связью.

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

2 голосов
/ 27 октября 2010

Ну, это не «известный шаблон», возможно, вы его и используете (нет проблем… шаблоны просто обычные решения хорошо известных проблем).

Однако, поскольку ваш пользовательский класс отвечает за загрузку самого себя, я бы сказал, что этот класс работает как DAO.

Как заявили другие пользователи, в вашем конструкторе слишком много логики. Конструкторы должны иметь только те параметры, которые необходимы для создания объекта и выполнять как можно меньше работы. Было бы предпочтительно, чтобы конструкторы также избегали исключения; Поскольку чем больше кода, тем выше вероятность исключения, чем больше вы делаете для конструктора, тем выше вероятность его выброса.

Теперь взгляните на ваш класс ... Я вижу, что у вашего "Пользователя" есть такие поля, как Имя, Рейтинг и т. Д. Разрешено, чтобы в течение времени жизни объекта пользователя он не имел такие поля заполнены? Вероятно, при создании нового пользователя это было бы правдой. Таким образом, для пользователя не обязательно иметь этот идентификатор, что сделало бы конструктор недействительным по правилу, которое я указывал.

Попробуйте создать статический метод Load, который возвращает нового пользователя или создаст фабрику. Это поможет вам в будущем с ремонтопригодностью и т. Д.

Наконец, попробуйте взглянуть на Шаблон репозитория . Вы можете использовать его вместо простой фабрики для обслуживания своего пользователя и других объектов.

2 голосов
/ 27 октября 2010

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

2 голосов
/ 27 октября 2010

Это не шаблон. Шаблон проектирования - это то, что решает общую проблему, например, как обновлять клиентов при изменении значения (Observer). Это на самом деле не проблема, это просто синтаксис языка. И ответ «да» на ваш второй вопрос.

2 голосов
/ 27 октября 2010

Я бы хотел назвать это вариантом Адаптера , потому что все, что вы действительно делаете, - это оборачиваете некоторую XML-структуру в более дружественный тип.

0 голосов
/ 27 октября 2010

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

Другая проблема с передачей данных XML вконструктор, в отличие от конкретного типа.Конкретный тип определяет известный набор свойств или полей, где xml не гарантирует структуру ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...