c# - 灵活使用对象包装器类

标签 c# java oop design-patterns

public interface iUserInfo
{
    string getUserName(int userId);
    string getUserAge(string username);
}

public class UserDb implements iUserInfo
{
    string getUserName(int userId)
    {
        //code to retrieve user info from the database
    }
}

public class UserTxtFile implements iUserInfo
{
    string getUserName(int userId)
    {
        //code to retrieve user info from the plain text file
    }
}

public class UserManager()
{
    private iUserInfo userInfo;

    public string retrieveUserData(string userName)
    {
        return userInfo.getUserAge(userName);
    }
}

我的教授说

"the above user manager class has a reference variable of type iUserInfo, so, if this reference is provided by a factory method or by any other means, the code of the manager class will be the same regardless of what implementation is provided.

This approach maximizes flexibilty if some implementations need to be altered during the process of software development, as higher level layers will not be affected at all."

我需要了解两件事;灵 active 最大化和工厂方法。

后者我猜可能是这样的

public class UserManager()
{
    private iUserInfo userInfo;
    private UserTxtFile  uTxtFile;
    private UserDb uDB;
    public iUserInfo GetUserInfoObjFactory(bool dbOrTxt)
    {
        return dbOrTxt? uTxtFile:uDB;
    }
    public string retrieveUserData(string userName)
    {
        return userInfo.getUserAge(userName);
    }
}

在讲座期间,我一直在做其他事情的白日梦,现在无法弄清楚那到底是什么意思?我很想了解得更深入一些,以防某些面试官可能攻击我不确定如何回答的开放性问题。

您是否也可以添加一些代码,在高层受到影响的示例情况下破坏上述源代码?非常感谢。

[更新] 我还发现诸如“我们需要接口(interface)来对通用方法进行分组”之类的答案并不是很有说服力。单独的抽象基类也有帮助。 例如,来自 2 个对象的飞行行为 {Penguin vs Bird}。我不能简单地告诉面试官根本就不需要IFly。即使我有数百万个需要 Fly 的不同对象,我也总是可以为它们中的每一个实现每个 Fly。因为即使我设计了 IFly,我仍然需要在实现类中这样做。能否请您提供更详细的案例或重新解释接口(interface)如何成为必须的?

最佳答案

我将稍微更改您的代码以进行解释

为什么要灵活?

这是您系统中的一段代码,它将打印用户名。更重要的是,让我们想象一下,直接使用 UserDb 的代码不只是一个,而是一百个,它们在您的系统中无处不在。

public void printUserName(String userId) {
  UserDb db = getUserDb();
  System.out.println(db.getUserName(userId));
}

现在,如果我们想从文本文件中检索用户信息怎么办?唯一的方法是将所有使用 UserDb 的代码更改为 UserTextFile。这将花费很多时间,而且很容易引入错误,因为我们可能会不小心更改不该更改的内容。

我们调用这些代码,UserDbCoupling .

所以这里我们有UserManager来解决这个问题

public class UserManager {

  private UserDb db;

  public UserManager(UserDb db) {
    this db = db;
  }

  public String getUserName(String userId) {
    // return user name using UserDb
  }
}

如果我们系统中的所有代码都使用UserManager 作为检索用户名的方式。当我们想切换到文本文件时,我们所能做的就是更改 UserManager 中的代码。

但是,在现实世界的编码中,UserManager 不可能这么简单,它们可能还有其他职责,例如在查询之前验证输入。我们可能仍会引入错误。

这就是为什么我们需要另一层来一次性消除这种耦合。

这是一个接口(interface)

public interface iUserInfo {    
  public String getUserName(int userId);
  public String getUserAge(string username);
}

... 我们让 UserManager 依赖于 iUserInfo

public class UserManager {

  private iUserInfo info;

  public UserManager(iUserInfo info) {
    this info = info;
  }

  public String getUserName(String userId) {
    // return user name using info
  }
}

现在,每当我们想将 UserDb 更改为 UserTextFile 时,我们所做的就是编写一个新的具体类 iUserInfoUserManager 永远不会注意到,因为它不需要知道实现的细节。

我们修改的代码越少,引入错误的可能性就越小。这就是我们需要这种灵 active 的原因。

此技术称为 Inversion of Control .


工厂方法?

工厂方法是处理对象创建的设计模式之一。检查此问题以获取更多信息

Factory, Abstract Factory and Factory Method

你的专业提到工厂方法的原因是因为这些模式用于隐藏对象的创建知识,iUserInfo 在这种情况下,来自其他类,这意味着这些方法/类是唯一的代码加上具体类。

因此我们可以最大限度地减少改变iUserInfo

实现的影响

界面对比抽象类 ?

接口(interface)使您所有的具体类都可以工作而无需扩展它。这很好,因为在 Java 中,您只能继承一个类。

另一方面,抽象类使您更容易处理在不同实现之间使用的通用代码。

您可以查看此问题以获取更多详细信息 Interface vs Base class

关于c# - 灵活使用对象包装器类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11814968/

相关文章:

c# - 如何使用 livecharts 动态创建笛卡尔图表

c# - 当我的 LINQ 查询将数据库记录作为 Enumerable 获取并在 foreach 循环中访问记录时会发生什么?

c# - 调试器正在寻找 executioncontext.cs,如何修复?

java - 二叉搜索树 findNode 方法始终返回根

java - 在 Java 中,为什么父类(super class)方法不能从子类实例访问 protected 或私有(private)方法/变量?

oop - 什么是不变性以及为什么我应该担心它?

c# - 我的 Windows 服务从应用程序读取不同的注册表路径

java - 用 Java 构建一个可模拟的日志记录 API,正确的方法

java.lang.NoClassDefFoundError : com/itextpdf/kernel/pdf/PdfWriter itext and gradle

ios - 在处理 Swift 对象和数组时,retainership 真的很重要吗?