繁体   English   中英

如何使用OOP进行设计

[英]How to design this using OOP

我有一个名为User的对象,其中包含Username,Age,Password email等属性。

我在ado.net代码中初始化此对象,如:

private User LoadUser(SqlDataReader reader)
{
      User user = new User();

      user.ID = (int)reader["userID"];
      // etc
}

现在说我创建一个继承自User的新对象,如:

public class UserProfile : User
{
     public string Url {get;set;}
}

现在我需要创建一个加载userprofile的方法,所以目前我在做:

public UserProfile LoadUserProfile(SqlDataReader reader)
{
         UserProfile profile = new UserProfile();

         profile.ID = (int)reader["userID"];
         // etc. copying the same code from LoadUser(..)
         profile.Url = (string) reader["url"];
}

是否有更多的OOP方法,所以我不必从LoadUser()在LoadUserProfile()镜像我的代码?

我希望我能做到这一点:

UserProfile profile = new UserProfile();

profile = LoadUser(reader);

// and then init my profile related properties

可以这样做吗?

将LodUser方法移动到User Base类并使其成为虚拟。 然后,在UserProfile方法中,您重写此方法。

public class User
{
   public virtual void Load(SqlDataReader reader)
   {
      this.Id = reader["Id"];
      //.. whatever else
   }
}

public class UserProfile : User
{
   public string ExtraProp {get;set;}
   public override void Load(SqlDataReader reader)
   {
      base.Load(reader);
      this.ExtraProp = reader["ExtraProp"];
   }
}

然后你可以做一些像:

UserProfile up = new UserProfile();
up.Load(myReader);

我真的不明白为什么用户配置文件继承自用户,从逻辑上讲,它没有多大意义。

对我来说有意义的是

public class UserProfile
{
     User user;
     public string Url {get;set;}
}

然后你可以有类似的东西

public UserProfile LoadUserProfile(SqlDataReader reader)
{
         User user = LoadUser(reader);
         UserProfile profile = new UserProfile(user);

          //load profile stuff from reader...
         return profile;
}

首先,为什么你的userprofile继承自用户。 UserProfile不是User。 最糟糕的是,他的遗传继承。

如果您不希望User和UserProfile对象知道SQL(persistence ignorance = good),您可以使用对现有对象进行操作的静态/扩展方法:

private static User LoadFromReader(this User user, SqlDataReader reader)
{
      user.ID = (int)reader["userID"];
      // etc

      return user;
}

public UserProfile LoadFromReader(this UserProfile profile, SqlDataReader reader)
{
     ((User)profile).LoadFromReader(reader);

     profile.Url = (string) reader["url"];
     // etc

     return profile;
}

然后调用代码可能如下所示:

UserProfile profile = new UserProfile().LoadFromReader(reader);

我会把它改成:

 class User 
 {
      public User(SqlDataReader reader)
      {
          Initialize(reader);
      }

      protected virtual void Initialize(SqlDataReader reader)
      {
           this.ID = (int)reader["userID"];
       // etc
      }
 }

 class UserProfile : User
 {
      public UserProfile(SqlDataReader reader) : base(reader) {}

      protected override void Initialize(SqlDataReader reader)
      {
           base.Initialize(reader); // Initialize "user" variables
           this.MyProperty = (int)reader["myProperty"];
      }
 }

这样,每个类初始化自己的值(从构造函数处理),并且只在一个地方有代码。

我会去这里的工厂课。 它会将事情分开来解决单一责任原则 :。 我的答案也是基于User的构建属性都可以从UserProfile访问。 UserProfile的构造函数可以接受User并获取其所有属性。

    public static class UserFactory
    {
        public static User LoadUser(SqlDataReader reader)
        {
            int id = (int)reader["userID"];
            return new User(id);
        }

        public static UserProfile LoadUserProfile(SqlDataReader reader)
        {
            User user = LoadUser(reader);
            // extra properties
            string url = (string)reader["url"];
            return new UserProfile(user, url);
        }
    }

使LoadUser虚拟和公共的。 UserProfile覆盖它。

简单的答案是覆盖LoadUser函数并在UserProfile类的覆盖函数定义顶部调用base.LoadUser(reader),然后根据UserProfile类的需要获取其余数据。

作为一般规则,此设置不应使用继承,而应使用聚合。 然而,为了说明这一点,它将会这样做。

制作一个带读者的构造函数:

public User(DbDataReader reader) {
   ID = reader.GetInt32(reader.GetOrdinal("userID"));
   // etc
}

用法:

User adam = new User(reader);

然后你可以让UserProfile中的构造函数调用基础构造函数:

public UserProfile(DbDataReader reader) : base(reader) {
   Url = reader.GetString(reader.GetOrdinal("url"));
}

我希望用户配置文件是用户类的成员

public class User
{
//...all current members of the user class...

     UserProfile profile;
}

public class UserProfile
{

     public string Url {get;set;}

}

除此之外,我会按照Reed Copsey的回答做一些事情

它听起来像你想要做的事情如下:

public class User { public Guid Id { get; set; } }
public class UserProfile : User { public string Url { get; set; } }

class MyReader
{
    private T LoadUser<T>(IDataReader reader)
        where T : User, new()
    {
        T user = new T();
        user.Id = reader.GetGuid(reader.GetOrdinal("userID"));
        return user;
    }

    public UserProfile LoadUserProfile(IDataReader reader)
    {
        UserProfile profile = LoadUser<UserProfile>(reader);
        profile.Url = (string)reader["url"];
        return profile;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM