什么时候在对象中使用工厂方法而不是factory类是一个好主意?
当前回答
我把工厂比作图书馆的概念。例如,您可以有一个库用于处理数字,另一个库用于处理形状。您可以将这些库的函数存储在逻辑上命名为Numbers或Shapes的目录中。这些是泛型类型,可以包括整数,浮点数,双元,长或矩形,圆形,三角形,在形状的情况下,五边形。
该系统采用了多态、依赖注入和控制反转等技术。
Factory Patterns的目的是:定义一个用于创建对象的接口,但是让子类来决定实例化哪个类。工厂方法允许类延迟实例化到子类。
假设你正在构建一个操作系统或框架,你正在构建所有的离散组件。
下面是PHP中工厂模式概念的一个简单示例。我可能不会完全理解,但这只是一个简单的例子。我不是专家。
class NumbersFactory {
public static function makeNumber( $type, $number ) {
$numObject = null;
$number = null;
switch( $type ) {
case 'float':
$numObject = new Float( $number );
break;
case 'integer':
$numObject = new Integer( $number );
break;
case 'short':
$numObject = new Short( $number );
break;
case 'double':
$numObject = new Double( $number );
break;
case 'long':
$numObject = new Long( $number );
break;
default:
$numObject = new Integer( $number );
break;
}
return $numObject;
}
}
/* Numbers interface */
abstract class Number {
protected $number;
public function __construct( $number ) {
$this->number = $number;
}
abstract public function add();
abstract public function subtract();
abstract public function multiply();
abstract public function divide();
}
/* Float Implementation */
class Float extends Number {
public function add() {
// implementation goes here
}
public function subtract() {
// implementation goes here
}
public function multiply() {
// implementation goes here
}
public function divide() {
// implementation goes here
}
}
/* Integer Implementation */
class Integer extends Number {
public function add() {
// implementation goes here
}
public function subtract() {
// implementation goes here
}
public function multiply() {
// implementation goes here
}
public function divide() {
// implementation goes here
}
}
/* Short Implementation */
class Short extends Number {
public function add() {
// implementation goes here
}
public function subtract() {
// implementation goes here
}
public function multiply() {
// implementation goes here
}
public function divide() {
// implementation goes here
}
}
/* Double Implementation */
class Double extends Number {
public function add() {
// implementation goes here
}
public function subtract() {
// implementation goes here
}
public function multiply() {
// implementation goes here
}
public function divide() {
// implementation goes here
}
}
/* Long Implementation */
class Long extends Number {
public function add() {
// implementation goes here
}
public function subtract() {
// implementation goes here
}
public function multiply() {
// implementation goes here
}
public function divide() {
// implementation goes here
}
}
$number = NumbersFactory::makeNumber( 'float', 12.5 );
其他回答
我喜欢从我的类是“人”的角度来考虑设计模式,而模式是人们彼此交谈的方式。
所以,对我来说,工厂模式就像一个招聘机构。你的公司需要不同数量的工人。这个人可能知道一些他们需要雇佣的人的信息,但仅此而已。
所以,当他们需要一个新员工时,他们会打电话给招聘机构,告诉他们他们需要什么。现在,要真正雇佣一个人,你需要知道很多东西——福利,资格验证,等等。但是招聘的人不需要知道这些——招聘机构会处理所有这些。
以同样的方式,使用Factory允许使用者创建新对象,而不必知道它们是如何创建的,或者它们的依赖关系是什么——他们只需要给出他们实际需要的信息。
public interface IThingFactory
{
Thing GetThing(string theString);
}
public class ThingFactory : IThingFactory
{
public Thing GetThing(string theString)
{
return new Thing(theString, firstDependency, secondDependency);
}
}
现在,ThingFactory的消费者可以得到一个Thing,而不需要知道Thing的依赖关系,除了来自消费者的字符串数据。
UML从
Product:它定义Factory方法创建的对象的接口。
ConcreteProduct:实现Product接口
创建者:声明Factory方法
ConcreateCreator:实现Factory方法以返回ConcreteProduct的实例
问题陈述:使用定义游戏界面的工厂方法创建游戏工厂。
代码片段:
import java.util.HashMap;
/* Product interface as per UML diagram */
interface Game{
/* createGame is a complex method, which executes a sequence of game steps */
public void createGame();
}
/* ConcreteProduct implementation as per UML diagram */
class Chess implements Game{
public Chess(){
}
public void createGame(){
System.out.println("---------------------------------------");
System.out.println("Create Chess game");
System.out.println("Opponents:2");
System.out.println("Define 64 blocks");
System.out.println("Place 16 pieces for White opponent");
System.out.println("Place 16 pieces for Black opponent");
System.out.println("Start Chess game");
System.out.println("---------------------------------------");
}
}
class Checkers implements Game{
public Checkers(){
}
public void createGame(){
System.out.println("---------------------------------------");
System.out.println("Create Checkers game");
System.out.println("Opponents:2 or 3 or 4 or 6");
System.out.println("For each opponent, place 10 coins");
System.out.println("Start Checkers game");
System.out.println("---------------------------------------");
}
}
class Ludo implements Game{
public Ludo(){
}
public void createGame(){
System.out.println("---------------------------------------");
System.out.println("Create Ludo game");
System.out.println("Opponents:2 or 3 or 4");
System.out.println("For each opponent, place 4 coins");
System.out.println("Create two dices with numbers from 1-6");
System.out.println("Start Ludo game");
System.out.println("---------------------------------------");
}
}
/* Creator interface as per UML diagram */
interface IGameFactory {
public Game getGame(String gameName);
}
/* ConcreteCreator implementation as per UML diagram */
class GameFactory implements IGameFactory {
HashMap<String,Game> games = new HashMap<String,Game>();
/*
Since Game Creation is complex process, we don't want to create game using new operator every time.
Instead we create Game only once and store it in Factory. When client request a specific game,
Game object is returned from Factory instead of creating new Game on the fly, which is time consuming
*/
public GameFactory(){
games.put(Chess.class.getName(),new Chess());
games.put(Checkers.class.getName(),new Checkers());
games.put(Ludo.class.getName(),new Ludo());
}
public Game getGame(String gameName){
return games.get(gameName);
}
}
public class NonStaticFactoryDemo{
public static void main(String args[]){
if ( args.length < 1){
System.out.println("Usage: java FactoryDemo gameName");
return;
}
GameFactory factory = new GameFactory();
Game game = factory.getGame(args[0]);
if ( game != null ){
game.createGame();
System.out.println("Game="+game.getClass().getName());
}else{
System.out.println(args[0]+ " Game does not exists in factory");
}
}
}
输出:
java NonStaticFactoryDemo Chess
---------------------------------------
Create Chess game
Opponents:2
Define 64 blocks
Place 16 pieces for White opponent
Place 16 pieces for Black opponent
Start Chess game
---------------------------------------
Game=Chess
这个例子通过实现FactoryMethod展示了一个Factory类。
Game is the interface for all type of games. It defines complex method: createGame() Chess, Ludo, Checkers are different variants of games, which provide implementation to createGame() public Game getGame(String gameName) is FactoryMethod in IGameFactory class GameFactory pre-creates different type of games in constructor. It implements IGameFactory factory method. game Name is passed as command line argument to NotStaticFactoryDemo getGame in GameFactory accepts a game name and returns corresponding Game object.
工厂:
创建对象而不向客户端公开实例化逻辑。
FactoryMethod
定义一个用于创建对象的接口,但是让子类来决定实例化哪个类。Factory方法允许类延迟实例化到子类
用例:
何时使用:客户端不知道在运行时需要创建什么具体的类,而只是想获得一个可以完成这项工作的类。
这真的是个品味问题。工厂类可以根据需要进行抽象/接口,而工厂方法是轻量级的(而且往往是可测试的,因为它们没有定义的类型,但它们需要一个众所周知的注册点,类似于服务定位器,但用于定位工厂方法)。
GOF定义:
定义一个用于创建对象的接口,但是让子类来决定实例化哪个类。工厂方法允许类延迟实例化到子类。
一般例子:
public abstract class Factory<T> {
public abstract T instantiate(Supplier<? extends T> supplier);
}
具体类
public class SupplierFactory<T> extends Factory<T> {
@Override
public T instantiate(Supplier<? extends T> supplier) {
return supplier.get();
}
}
实现
public class Alpha implements BaseInterface {
@Override
public void doAction() {
System.out.println("The Alpha executed");
}
}
public class Beta implements BaseInterface {
@Override
public void doAction() {
System.out.println("The Beta executed");
}
}
public interface BaseInterface {
void doAction();
}
public class Main {
public static void main(String[] args) {
Factory<BaseInterface> secondFactory = new SupplierFactory<>();
secondFactory.instantiate(Beta::new).doAction();
secondFactory.instantiate(Alpha::new).doAction();
}
}
短暂的优势
您正在分离可以变化的代码和不变的代码(即,使用简单工厂模式的优点仍然存在)。这种技术可以帮助您轻松地维护代码。 你的代码不是紧密耦合的;因此,你可以随时在系统中添加新的类,如Lion、Beer等,而无需修改现有的体系结构。因此,您遵循了“修改封闭,扩展开放”的原则。
我把工厂比作图书馆的概念。例如,您可以有一个库用于处理数字,另一个库用于处理形状。您可以将这些库的函数存储在逻辑上命名为Numbers或Shapes的目录中。这些是泛型类型,可以包括整数,浮点数,双元,长或矩形,圆形,三角形,在形状的情况下,五边形。
该系统采用了多态、依赖注入和控制反转等技术。
Factory Patterns的目的是:定义一个用于创建对象的接口,但是让子类来决定实例化哪个类。工厂方法允许类延迟实例化到子类。
假设你正在构建一个操作系统或框架,你正在构建所有的离散组件。
下面是PHP中工厂模式概念的一个简单示例。我可能不会完全理解,但这只是一个简单的例子。我不是专家。
class NumbersFactory {
public static function makeNumber( $type, $number ) {
$numObject = null;
$number = null;
switch( $type ) {
case 'float':
$numObject = new Float( $number );
break;
case 'integer':
$numObject = new Integer( $number );
break;
case 'short':
$numObject = new Short( $number );
break;
case 'double':
$numObject = new Double( $number );
break;
case 'long':
$numObject = new Long( $number );
break;
default:
$numObject = new Integer( $number );
break;
}
return $numObject;
}
}
/* Numbers interface */
abstract class Number {
protected $number;
public function __construct( $number ) {
$this->number = $number;
}
abstract public function add();
abstract public function subtract();
abstract public function multiply();
abstract public function divide();
}
/* Float Implementation */
class Float extends Number {
public function add() {
// implementation goes here
}
public function subtract() {
// implementation goes here
}
public function multiply() {
// implementation goes here
}
public function divide() {
// implementation goes here
}
}
/* Integer Implementation */
class Integer extends Number {
public function add() {
// implementation goes here
}
public function subtract() {
// implementation goes here
}
public function multiply() {
// implementation goes here
}
public function divide() {
// implementation goes here
}
}
/* Short Implementation */
class Short extends Number {
public function add() {
// implementation goes here
}
public function subtract() {
// implementation goes here
}
public function multiply() {
// implementation goes here
}
public function divide() {
// implementation goes here
}
}
/* Double Implementation */
class Double extends Number {
public function add() {
// implementation goes here
}
public function subtract() {
// implementation goes here
}
public function multiply() {
// implementation goes here
}
public function divide() {
// implementation goes here
}
}
/* Long Implementation */
class Long extends Number {
public function add() {
// implementation goes here
}
public function subtract() {
// implementation goes here
}
public function multiply() {
// implementation goes here
}
public function divide() {
// implementation goes here
}
}
$number = NumbersFactory::makeNumber( 'float', 12.5 );