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.”
我需要了解两件事;灵活性最大化和工厂方法.
后者我猜它可能是这样的
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);
}
}
在演讲期间,我对其他事情做了一些白日梦,现在无法弄清楚究竟是什么意思?我想更深入地了解一下,以防一些采访者用更开放的问题来攻击我,我不知道如何回答.
在高级别图层受到影响时,您是否还可以添加一些代码来破坏上述源代码?非常感谢.
[更新]
我也找到了一个答案,例如“我们需要接口来分组常用方法”并不是很有说服力.仅抽象基类也有帮助.
例如,来自2个对象{Penguin vs Bird}的Fly行为.我不能简单地告诉面试官,根本需要IFly.即使我有数百万个需要Fly的不同对象,我也可以为每个对象实现每个Fly.因为即使我设计了IFly,我仍然需要在实现类中执行此操作.您能否提供更多详细案例或重新解释界面必须如何?
最佳答案 我会稍微改变你的代码以便解释
为何灵活?
这是系统中的一段代码,用于打印用户名.更重要的是,让我们的形象不仅仅是一个,而是直接使用UserDb的一百个代码,它们在你的系统中无处不在.
public void printUserName(String userId) {
UserDb db = getUserDb();
System.out.println(db.getUserName(userId));
}
现在,如果我们想从文本文件中检索用户信息怎么办?执行此操作的唯一方法是将使用UserDb的所有代码更改为UserTextFile.它需要花费很多时间,并且它可以很容易地引入错误,因为我们可能会意外地改变我们不应该做的事情.
我们称这些代码和UserDb为Coupling.
所以这里我们有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不能那么简单,它们可能还有其他责任,例如在查询之前验证输入.我们可能仍会引入错误.
这就是为什么我们需要另一层来一次性删除这种耦合.
这是一个界面
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时,我们所做的就是编写一个新的具体类iUserInfo. UserManager永远不会注意到,因为它不需要知道实现的细节.
我们修改的代码越少,引入错误的机会就越少.这就是我们想要这种灵活性的原因.
这种技术称为Inversion of Control.
工厂方法?
工厂方法是处理对象创建的设计模式之一.查看此问题以获取更多信息
Factory, Abstract Factory and Factory Method
你的职业提到工厂方法的原因,是因为这些模式用于隐藏对象的创建知识,在这种情况下,iUserInfo来自其他类,这意味着这些方法/类是唯一与具体类相结合的代码.
因此,我们可以最大限度地减少更改iUserInfo实现的影响
接口v.s.抽象类?
界面使您的所有具体类工作无需扩展它.这很好,因为在Java中,您只能从一个类继承.
另一方面,抽象类使您更容易处理在不同实现之间使用的公共代码.
您可以查看此问题以获取更多详细信息
Interface vs Base class