我正在开发一个程序,我想使用接口。类似于Bukkit用于他们的Player类的方式,here。我多次观看和阅读界面上的教程,甚至尝试自己测试,没有运气。
假设我有一个“User”界面,其方法占位符返回一个字符串。该方法将命名为getName()。
我想做
User user = (INSTANTIATE SOMEHOW);
System.out.println(user.getName());
这在Bukkit的实现中以同样的方式实现
Player player = Server.getPlayer("Jimmothy");
System.out.println(player.getName());
我无法弄清楚如何让这样的东西发挥作用。为了实例化播放器类,您可以使用众多“getPlayer()”方法之一。唯一的问题是包含这些方法的类也是接口,所以我不知道如何获取接口的实例。搜索代码也无济于事,因为我似乎无法找到这些类中的方法是否实际使用Overrides或其他方法构建的。 (如果这是覆盖的工作方式)。
谁知道,也许我需要知道的是如何实例化或获取用户界面的实例并且我已经完成了设置。我知道你不能使用“new ClassName();”创建接口实例。我从来没有真正了解它们,但我真的很想。
这似乎是一个非常愚蠢的问题,我确信答案很简单,但帮助会很棒! :)谢谢你的阅读。
答案 0 :(得分:4)
恭喜,您找到了factory method!让我们直接跳到代码。
Test.java
:
interface Player {
String getName();
}
class PlayerImpl implements Player {
public PlayerImpl(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
private String name;
}
class Server {
public static Player getPlayer(String name) {
return new PlayerImpl(name);
}
}
public class Test {
public static void main(String[] args) {
Player foo = Server.getPlayer("foo");
System.out.println(foo.getName());
}
}
如您所见,Server
类使用static
方法将UserImpl
的实例作为类型User
返回。那是工厂方法。
这似乎(并且,在这种情况下,是)不必要的复杂化,但它具有关键优势:它将某个“具体”类的使用与它实现的接口分离。这样可以提供更大的灵活性:
它隐藏了实现,因此您可以在多个不同的实现之间自由切换,只要它们都实现User
接口即可。从外面看,它们看起来都一样。
它允许实现池化(每次请求某个名称,给予相同的实例)或任何其他分配策略。
它让您控制对象创建。您可以执行,例如,检查。
如果提供了工厂方法,则不应使用new
实例化对象。如果确实需要,您将不得不寻找该接口的实现。例如,PlayerImpl
:
Player foo = new PlayerImpl("foo");
同样,这不是PlayerImpl
的使用方式。
答案 1 :(得分:2)
Bukkit在CraftBukkit(DMCA'd)中实现Server
。单例传递给Bukkit
,您可以使用Bukkit.getServer()
通过API检索。但是,您对Server#getPlayer(String)
方法的工作原理感兴趣。
在CraftServer
中,具体实现了getPlayer(String)
方法,它从玩家的名字中检索玩家。服务器中的播放器存储在一个集合表中,其名称/ UUID指向实际的Player
- 由CraftPlayer
实现。每次玩家加入时,都会实例化一个新的CraftPlayer
并将其放入集合中。
因此,要自己执行此操作,必须同时实现检索接口和要检索的实际对象。实质上:
interface Player {
void kick(String message);
}
class CraftPlayer implements Player {
@Override public void kick(String message) {
// Implementation
}
}
interface Server {
Player getPlayer(String name);
}
class CraftServer implements Server {
private final Map<String, Player> players = new HashMap<>();
public CraftServer() {
Bukkit.setServer(this);
}
@Override public Player getPlayer(String name) {
return players.get(name);
}
public void joinPlayer(String name) {
Player p = new CraftPlayer();
players.put(name, p);
}
}
class Bukkit {
private Server server;
public void setServer(Server server) {
if (server == null) this.server = server;
}
public Server getServer() {
return server;
}
}
// Usage
new CraftServer();
Player p = Bukkit.getServer().getPlayer("Name");
if (p == null) {
// Not online
System.out.println("No player with that name is online");
return;
}
p.kick("lol");