Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 工厂方法模式-此模式需要什么?_Design Patterns_Factory Pattern - Fatal编程技术网

Design patterns 工厂方法模式-此模式需要什么?

Design patterns 工厂方法模式-此模式需要什么?,design-patterns,factory-pattern,Design Patterns,Factory Pattern,我有一个抽象类factoryfactory,带有factory方法getProduct()和他的子类 我有抽象类productproduct和他的子类 类工厂创建类产品的对象 abstract class Factory { abstract function getProduct(); } class FirstFactory extends Factory { public function getProduct() { return new FirstPro

我有一个抽象类factory
factory
,带有factory方法
getProduct()
和他的子类

我有抽象类product
product
和他的子类

类工厂创建类产品的对象

abstract class Factory {
    abstract function getProduct();
}
class FirstFactory extends Factory {
    public function getProduct() {
        return new FirstProduct();
    }
}

abstract class Product {
};
class FirstProduct extends Product {
}
因此,我可以使用以下客户端代码:

$factory = new FirstFactory();
$firstProduct = $factory->getProduct();
$factory = new SecondFactory();
$secondProduct = $factory->getProduct();
问题:这种模式需要什么?因为在客户端代码中,我只能使用直接类:

$firstProduct = new FirstProduct();
$secondProduct = new SecondProduct();

如果您在编译时知道
firstProduct
始终为
firstProduct
类型,
secondProduct
始终为
secondProduct
类型,则不需要工厂方法


工厂方法仅在您希望创建的产品可能是
FirstProduct
SecondProduct
时有用,具体取决于工厂的运行时类型。例如,工厂的类型可能由用户输入决定。

如果您在编译时知道
firstProduct
始终是
firstProduct
类型,
secondProduct
始终是
secondProduct
类型,则不需要工厂方法


工厂方法仅在您希望创建的产品可能是
FirstProduct
SecondProduct
时有用,具体取决于工厂的运行时类型。例如,工厂的类型可能由用户输入决定。

可以注入工厂而不是实际的类。假设您有一个只能在运行时基于某些特定条件实例化的类,在这种情况下,您不能执行新的Foo(…args)。
一个选项是注入FooFactory,并让它为您创建Foo实例。

可以注入工厂而不是实际的类。假设您有一个只能在运行时基于某些特定条件实例化的类,在这种情况下,您不能执行新的Foo(…args)。
一种选择是注入FooFactory,让它为您创建Foo实例。

需要注意的是,Factory模式并不总是最佳解决方案,对于简单的情况,使用simple
new
更好。例如,如果没有工厂,您的示例可能会更好。 当您不需要处理类的精确实现,而是停留在“抽象层”(例如接口和抽象类)时,工厂模式将发挥其全部功能。您可以看看“依赖倒置原则DIP”(依赖抽象,不依赖具体类)

工厂用例:用一行切换数据库 例如,假设您有一个使用数据库系统的软件。无论出于何种原因,您都知道所使用的具体数据库(MongoDB、SQL…)可能会在以后更改。(甚至在开发过程中只需要文件中的假硬编码数据库)。工厂模式允许您通过调用正确的工厂,在一行中从一个工厂切换到另一个工厂,因为所有的实现都依赖于抽象。(这实际上是DAO模式,它充分利用了Factory模式,有关更多信息,请参阅oracle文档:)

具体例子:有两个派系的游戏 这里是一个具体而简单的实现示例

你有两个单位
  • 牡丹
  • 战士
你有两个派系
  • 兽人
    • 虎皮牡丹
    • 兽人战士
    • 人牡丹
    • 人类战士
2名球员
  • 兽人玩家(仅使用兽人单位)
  • 人类玩家(仅使用人类单位)
您希望实例化这两个播放器,但具体的播放器类应该以更通用的方式实现,以便以后可以重用。这在增加几个新阵营的情况下也非常重要,你不想花时间回到你的玩家职业

代码示例 要构建并运行它,请复制Main.java,然后
javacmain.java
javamain

结果应该是

看看玩家类是如何被任何势力重用的,定义巫婆势力的唯一一行就是工厂。(您甚至可以添加一个单例)

更多资源 这些是我非常欣赏的书(关于设计模式)

  • 头先设计模式()
  • 设计模式、可重用对象的元素()

需要注意的是,工厂模式并不总是最好的解决方案,对于简单的情况,使用simple
new
更好。例如,如果没有工厂,您的示例可能会更好。 当您不需要处理类的精确实现,而是停留在“抽象层”(例如接口和抽象类)时,工厂模式将发挥其全部功能。您可以看看“依赖倒置原则DIP”(依赖抽象,不依赖具体类)

工厂用例:用一行切换数据库 例如,假设您有一个使用数据库系统的软件。无论出于何种原因,您都知道所使用的具体数据库(MongoDB、SQL…)可能会在以后更改。(甚至在开发过程中只需要文件中的假硬编码数据库)。工厂模式允许您通过调用正确的工厂,在一行中从一个工厂切换到另一个工厂,因为所有的实现都依赖于抽象。(这实际上是DAO模式,它充分利用了Factory模式,有关更多信息,请参阅oracle文档:)

具体例子:有两个派系的游戏 这里是一个具体而简单的实现示例

你有两个单位
  • 牡丹
  • 战士
你有两个派系
  • 兽人
    • 虎皮牡丹
    • 兽人战士
    • 人牡丹
    • 人类战士
2名球员
  • 兽人玩家(仅使用兽人单位)
  • 人类玩家(仅使用人类单位)
你想马上离开吗
// Factories ----------------------------------------

abstract class AbsUnitFactory {
    public abstract Warrior creaWarrior();
    public abstract Peon creaPeon();
}

class OrcFactory extends AbsUnitFactory {
    public Warrior creaWarrior() {
        return new OrcWarrior();
    }
    public Peon creaPeon() {
        return new OrcPeon();
    }
}

class HumanFactory extends AbsUnitFactory {
    public Warrior creaWarrior() {
        return new HumanWarrior();
    }
    public Peon creaPeon() {
        return new HumanPeon();
    }
}

abstract class Unit {
    public abstract String getRole();
    public abstract String getFaction();

    @Override
    public String toString() {
        String str = new String();
        str += "[UNIT]\n";
        str += "    Role: " + this.getRole() + "\n";
        str += "    Faction: " + this.getFaction() + "\n";
        return str;
    }
}


// Warrior Units ----------------------------------------

abstract class Warrior extends Unit {
    @Override
    public String getRole() {
        return "I'm a badass Warrior with the biggest sword!";
    }
}

class OrcWarrior extends Warrior {
    @Override
    public String getFaction() {
        return "Orc";
    }
}

class HumanWarrior extends Warrior {
    @Override
    public String getFaction() {
        return "Human";
    }
}


// Peon Units ----------------------------------------

abstract class Peon extends Unit {
    @Override
    public String getRole() {
        return "I'm a little simple peon... Ready to work.";
    }
}

class HumanPeon extends Peon {
    @Override
    public String getFaction() {
        return "Human";
    }
}

class OrcPeon extends Peon {
    @Override
    public String getFaction() {
        return "Orc";
    }
}


// Main components ----------------------------------------

class Player {
    private AbsUnitFactory  factory;
    private Peon            myPeon;
    private Warrior         myWarrior;

    public Player(AbsUnitFactory pFactory) {
        this.factory    = pFactory;
        this.myPeon     = this.factory.creaPeon();
        this.myWarrior  = this.factory.creaWarrior();
    }

    @Override
    public String toString() {
        return this.myPeon.toString() + this.myWarrior.toString();
    }
}

class Main {
    public static void main(String[] args) {
        AbsUnitFactory  humanFactory    = new HumanFactory();
        AbsUnitFactory  orcFactory      = new OrcFactory();
        Player          humanPlayer     = new Player(humanFactory);
        Player          orcPlayer       = new Player(orcFactory);

        System.out.println("***** Human player *****");
        System.out.println(humanPlayer.toString());

        System.out.println("***** Orce player *****");
        System.out.println(orcPlayer.toString());
    }
}