为什么我们需要传递InterfaceFactory来获取对象而不是仅传递特定对象

时间:2017-11-25 13:41:27

标签: java factory-pattern

有一个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

所以我想知道工厂方法的优点是什么?

2 个答案:

答案 0 :(得分:0)

问题对于该网站而言过于宽泛,因为它是关于理论而不是要解决的问题。

但简而言之:这是一种模式,您可以自由使用其他模式。

接口的主要目的是让不同的类具有相同方法的不同实现。因此,工厂提供了以不同方式创建对象的能力,而不是处理更复杂的构造函数。作为示例,您需要使用不同的代码来构造具有相同参数的对象,可能基于运行代码的OS或app服务器。那么,你将如何做到这一点?然后有一种方法可以为Linux提供工厂,为Windows提供另一种工具等等。

你不需要在任何地方......

另一个优点是内存管理和垃圾收集器。通过使用 new 内部方法,很有可能最终得到孤立的实例,该实例只能通过非常昂贵的完整GC进行清理。工厂作为Singleton永远不会发生,

BTW:在您的简单示例中,既不需要接口也不需要工厂。

同样,有许多模式可供选择以满足实际需求。

答案 1 :(得分:0)

工厂模式的存在是为了提供一个面向对象的函数式编程习惯用法:提供一个生成值的函子。大多数情况下,您会看到Factory与Strategy模式相结合,其中您有一个表示某种做法的界面,以及该界面的多个具体实现,它们代表了执行该操作的不同方法。 Factory的价值在于它抽象了策略的创建

在实践中,我发现这在两种情况下很有用:

  1. 当客户端代码需要选择策略时,库代码需要控制策略的使用时间和频率。这符合您的游戏示例:GameFactory表示游戏的(国际象棋,棋子等),而Game实例代表特定游戏。如果你正在编写一个在不同玩家之间进行比赛的比赛,你需要用GameFactory构建它来告诉它要玩什么样的游戏,但是锦标赛本身将决定要开始的游戏数量以及如何操纵每场比赛。锦标赛不能仅仅new Chess()new Checkers(),因为目标是使锦标赛级别与游戏类型无关,以便它可以重复使用。

  2. 当创建一个很复杂的值并且你想要部分应用构造函数时,工厂也很有用。这种方法通常与依赖注入模式一起使用。例如,考虑您现在添加第三种游戏PokerPoker游戏需要一个随机数生成器,以便它知道如何对卡进行随机播放。你如何适应现有的GameFactory / Game / Tournament结构? PokerFactory对象将随机数生成器作为参数,它将负责将随机数生成器传递给它创建的任何PokerGame个对象。使用GameFactory / Game API的类,比如Tournament,不需要知道某些游戏需要随机数生成器,有些则不需要;知识将被抽象出来。

  3. 退一步:像大多数OO设计模式一样,工厂模式的整个目的是减少耦合增加凝聚力。您不希望您的锦标赛课程耦合到任何特定游戏;解耦代码可以使程序的不同部分彼此独立地更改。

    更进一步的步骤:围绕软件工程的大部分知识和最佳实践都来自大型软件项目,有如此多的代码行,没有人能记住到处发生的一切,并且有很多人在项目上工作,协调项目不同部分之间的工作成为最重要的问题之一。存在许多设计模式,因为它们在程序的不同部分之间定义“接缝”,以便将您需要在脑中保持的概念划分为一次。这允许两个或更多程序员同时在不同的隔间上工作,并使您更容易确保每个隔间都正确。

    在学习编程语言或第一次学习编程时所编写的“玩具”程序中,这些划分程序的策略可能看似多余或者只是令人困惑。事实上,如果你不必要地应用这些模式,那么它们实际上会使事情变得更糟,而不是更好。但是当你接近大量代码时,这些技术是你的工具带中的“工具”:这两种技术都可以让你更好地理解现有代码是如何划分的,这样你就可以划分你编写的代码。

    TL; DR:“一切都应尽可能简单,但不能简单。”