这种模式叫什么?

时间:2010-10-27 12:42:37

标签: c# design-patterns

当你在一个对象的构造函数中给一个参数并且该对象用参数填充它的字段时,这个模式被称为什么?

例如:

/// <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 个答案:

答案 0 :(得分:8)

对我而言,它更像是一种反模式:在构造函数中包含xml请求,读取和字段初始化。 也许你可以像这样使用Factory模式:

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

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

也许你可以添加一些单例以便能够对你的类进行单元测试。

答案 1 :(得分:2)

我想把它称为Adaptor的变种,因为你所做的只是将一些XML结构包装成更友好的类型。

答案 2 :(得分:2)

这不是一种模式。设计模式可以解决常见问题,例如在值更改时如何更新客户端(Observer)。这不是一个真正的问题,它只是语言语法。你的第二个问题答案是肯定的。

答案 3 :(得分:2)

在构造函数中执行如此繁重的操作是不好的做法,我建议您将构造函数设为私有并创建将返回User实例的静态Load方法。我不知道这种模式是怎么称呼的。

答案 4 :(得分:2)

嗯,这不是一个“已知的模式”,可能是你使用的模式(没有问题......模式只是那些,常见的问题解决方案)。

但是,由于您的用户类负责加载自身,我会说该类正在作为DAO工作。

正如其他用户所说,你的构造函数中有太多的逻辑。构造函数应该只有创建对象所必需的参数,并尽可能少地工作。构造函数最好避免抛出异常;由于代码越多,异常的可能性越大,对构造函数的处理越多,抛出的机会就越大。

现在,看看你的班级...我看到你的“用户”有字段,如姓名,评级等。在用户对象的生命周期中,它是不允许的,因为它没有这些领域填满了?也许,在创建新用户时,情况确实如此。所以这不是用户拥有此ID的先决条件,这会使构造函数因我所说的规则而无效。

尝试制作一个返回新用户或创建工厂的Load静态方法。它将在未来帮助您提供可维护性等。

最后,请尝试查看 Repository Pattern 。您可以使用它而不是普通工厂来维护您的用户和其他对象。

答案 5 :(得分:2)

执行以下操作绝对违反了Law of Demeter

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

你真的不希望有这么长的方法调用链。让朋友从其参数中询问值是一个更好的设计,耦合少得多。

子部分,朋友,访客......应该填充自己没有完成工作。这将您的顾虑分开。它还使测试变得更容易,因为您可以存根toplevel参数,而无需深入三层以满足构造函数。

答案 6 :(得分:0)

在您的示例中,我倾向于将任何所需的数据传递到构造函数中,因为它定义了我的类所需的 dependancy

将xml数据传递给构造函数而不是具体类型的另一个问题。具体类型定义了一组已知的属性或字段,其中xml不保证结构......