有一个Interface and Factories
的例子在" Thinking In Java"如下:
(1)定义Game和GameFactory接口
interface Game { boolean move(); }
interface GameFactory { Game getGame(); }
(2)写下他们的实现
class Checkers implements Game {
private int moves = 0;
private static final int MOVES = 3;
public boolean move() {
System.out.println("Checkers move " + moves);
return ++moves != MOVES;
}
}
class CheckersFactory implements GameFactory {
public Game getGame() { return new Checkers(); }
}
class Chess implements Game {
private int moves = 0;
private static final int MOVES = 4;
public boolean move() {
print("Chess move " + moves);
return ++moves != MOVES;
}
}
class ChessFactory implements GameFactory {
public Game getGame() { return new Chess(); }
}
(3)和客户端代码
public class Games {
public static void playGame(GameFatory factory) {
Game s = factory.getGame();
while (s.move());
}
public static void main(String[] args) {
playGame(new CheckersFactory());
playGame(new ChessFactory());
}
}
对于客户端代码,为什么我们懒得将GameFactory
传递给playGame
的函数?
我们可以将Game
设置为参数,如下所示:
public class Games {
public static void playGame(Game game) {
while (game.move());
}
public static void main(String[] args) {
playGame(new Checkers());
playGame(new Chess());
}
}
因此,我们无需创建GameFactory
来获取Game
所以我想知道工厂方法的优点是什么?
答案 0 :(得分:0)
问题对于该网站而言过于宽泛,因为它是关于理论而不是要解决的问题。
但简而言之:这是一种模式,您可以自由使用其他模式。
接口的主要目的是让不同的类具有相同方法的不同实现。因此,工厂提供了以不同方式创建对象的能力,而不是处理更复杂的构造函数。作为示例,您需要使用不同的代码来构造具有相同参数的对象,可能基于运行代码的OS或app服务器。那么,你将如何做到这一点?然后有一种方法可以为Linux提供工厂,为Windows提供另一种工具等等。
你不需要在任何地方......
另一个优点是内存管理和垃圾收集器。通过使用 new 内部方法,很有可能最终得到孤立的实例,该实例只能通过非常昂贵的完整GC进行清理。工厂作为Singleton永远不会发生,
BTW:在您的简单示例中,既不需要接口也不需要工厂。
同样,有许多模式可供选择以满足实际需求。
答案 1 :(得分:0)
工厂模式的存在是为了提供一个面向对象的函数式编程习惯用法:提供一个生成值的函子。大多数情况下,您会看到Factory与Strategy模式相结合,其中您有一个表示某种做法的界面,以及该界面的多个具体实现,它们代表了执行该操作的不同方法。 Factory的价值在于它抽象了策略的创建。
在实践中,我发现这在两种情况下很有用:
当客户端代码需要选择策略时,库代码需要控制策略的使用时间和频率。这符合您的游戏示例:GameFactory
表示游戏的种(国际象棋,棋子等),而Game
实例代表特定游戏。如果你正在编写一个在不同玩家之间进行比赛的比赛,你需要用GameFactory构建它来告诉它要玩什么样的游戏,但是锦标赛本身将决定要开始的游戏数量以及如何操纵每场比赛。锦标赛不能仅仅new Chess()
或new Checkers()
,因为目标是使锦标赛级别与游戏类型无关,以便它可以重复使用。
当创建一个很复杂的值并且你想要部分应用构造函数时,工厂也很有用。这种方法通常与依赖注入模式一起使用。例如,考虑您现在添加第三种游戏Poker
。 Poker
游戏需要一个随机数生成器,以便它知道如何对卡进行随机播放。你如何适应现有的GameFactory / Game / Tournament结构? PokerFactory
对象将随机数生成器作为参数,它将负责将随机数生成器传递给它创建的任何PokerGame
个对象。使用GameFactory / Game API的类,比如Tournament,不需要知道某些游戏需要随机数生成器,有些则不需要;知识将被抽象出来。
更进一步的步骤:围绕软件工程的大部分知识和最佳实践都来自大型软件项目,有如此多的代码行,没有人能记住到处发生的一切,并且有很多人在项目上工作,协调项目不同部分之间的工作成为最重要的问题之一。存在许多设计模式,因为它们在程序的不同部分之间定义“接缝”,以便将您需要在脑中保持的概念划分为一次。这允许两个或更多程序员同时在不同的隔间上工作,并使您更容易确保每个隔间都正确。
在学习编程语言或第一次学习编程时所编写的“玩具”程序中,这些划分程序的策略可能看似多余或者只是令人困惑。事实上,如果你不必要地应用这些模式,那么它们实际上会使事情变得更糟,而不是更好。但是当你接近大量代码时,这些技术是你的工具带中的“工具”:这两种技术都可以让你更好地理解现有代码是如何划分的,这样你就可以划分你编写的代码。
TL; DR:“一切都应尽可能简单,但不能简单。”