如何使用工厂创建使用策略模式的对象?

时间:2017-01-30 18:55:00

标签: oop design-patterns polymorphism factory

假设我们在网上商店有一个简单的付款功能。我们希望使用不同的交易处理器管理不同的交易:

  • 交易可以是付款或退款。
  • 交易处理器可以是Paypal或Payplug。

所以我们有以下几个类:

class PaymentTransaction implements Transaction {

}

class RefundTransaction implements Transaction {

}

class PaypalProcessor implements Processor {

}

class PayplugProcessor implements Processor {

}

正如this answer中所建议的,我们可以使用以下使用策略和多态的类。

class PaymentProcessor {
     private Processor processor;
     private Transaction transaction;

     public PaymentProcessor(Processor processor, Transaction transaction) {
          this.processor = processor;
          this.transaction = transaction;
     }

     public void processPayment() {
         processor.process(transaction);
     }
}

我们假设处理器和要使用的事务是从数据库中提供的。我想知道如何创建PaymentProcessor对象。

似乎只有一个方法的抽象工厂类仍然是有效的抽象工厂模式。所以,在这种情况下,我想知道使用抽象工厂是否相关。

  • 如果是,如何实施?
  • 如果不是,我们是否应该使用带有PaymentProcessorFactory类的 Factory Method 模式根据数据库中提供的详细信息创建具有两个属性的PaymentProcessor

在这种情况下,使用工厂的最佳做法是什么?

2 个答案:

答案 0 :(得分:2)

也许您可以使用构建器模式。在构建器模式中,有一个名为director的类,它知道创建复杂对象的算法。要创建组件,复杂对象是构建导演使用构建器。像这样,您可以更改特定组件以构建整个复杂对象。

在您的情况下,PaymentProcessor(复杂对象)由Payment和Processor组成,因此算法将它们注入PaymentProcessor。建造者应该建造零件。要构建paypal-refund组合,您应该创建一个返回PaypalProcessor和RefundTransaction的构建器。当您要创建payplug-payment时,构建器应返回PaymentTransaction和PayPlugProcessor。

public interface PaymentProcessorBuilder {
    public Transaction buildTransaction();
    public Processor buildProcessor();
}

public class PaypalRefundProcessorBuilder implements PaymentProcessorBuilder {
    public Transaction buildTransaction {
        return new RefundTransaction();
    }
    public Processor buildProcessor {
        return new PayPalProcessor();
    }
}

public class PayPlugPaymentProcessorBuilder implements PaymentProcessorBuilder {
    public Transaction buildTransaction {
        return PaymentTransaction();
    }
    public Processor buildProcessor {
        return new PayPlugProcessor();
    }
}

现在,Director可以使用构建器来组成PaymentProcessor:

publi PaymentProcessorDirector {
    public PaymentProcessor createPaymentProcessor(PaymentProcessorBuilder builder) {
        PaymentProcessor paymentProcessor = new PaymentProcessor();

        paymentProcessor.setTransaction(builder.buildTransaction());
        paymentProcessor.setProcessor(builder.buildProcessor());

        return paymentProcessor;
    }
}

创建的PaymentProcessor现在依赖于传递的Builder:

...
PaymentProcessorDirector director = new PaymentProcessorDirector();
PaymentProcessorBuilder builder = new PaypalRefundProcessorBuilder();

PaymentProcessor paymentProcessor = director.createPaymentProcessor(builder);
...

对于每个组合,您可以创建一个构建器。如果您将正确的构建器传递给导向器,则会返回所需的PaymentProcessor。

现在问题是如何获得正确的构建器。因此,您可以使用工厂,它接受一些事件参数并决定必须制作哪个构建器。您在导演中传递的此构建器将获得所需的PaymentProcessor。

注意:这只是此问题的一种可能解决方案。每种解决方案都有优点和缺点。找到正确的解决方案,你可以平衡好事和坏事。

PS:希望语法正确。我不是一个java开发人员。

编辑: 您可以将构建器模式的director解释为PaymentProcessorFactory,其中构建器本身作为构建PaymentProcessor部分的策略

答案 1 :(得分:2)

  

我们假设处理器和要使用的事务是从数据库中提供的。我想知道如何创建PaymentProcessor对象。

我将定义一个接口,我可以适应数据库结果或任何其他可以提供创建PaymentProcessor所需数据的源。这对于单元测试也很有用。

public interface PaymentProcessorFactoryArgs {
  String getProcessorType();
  String getTransactionType();
}

然后实现这样的工厂。

public class PaymentProcessorFactory {

  private Map<String, Processor> processorMap = new HashMap<>();
  private Map<String, Transaction> transactionMap = new HashMap<>();

  public PaymentProcessorFactory() {
    processorMap.put("paypal", new PaypalProcessor());
    processorMap.put("payplug", new PayplugProcessor());

    transactionMap.put("refund", new RefundTransaction());
    transactionMap.put("payment", new PaymentTransaction());
  }

  public PaymentProcessor create(PaymentProcessorFactoryArgs factoryArgs) {
    String processorType = factoryArgs.getProcessorType();
    Processor processor = processorMap.get(processorType);
    if(processor == null){
      throw new IllegalArgumentException("Unknown processor type " + processorType);
    }

    String transactionType = factoryArgs.getTransactionType();
    Transaction transaction = transactionMap.get(transactionType);
    if(transaction == null){
      throw new IllegalArgumentException("Unknown transaction type " + processorType);
    }

    return new PaymentProcessor(processor, transaction);
  }
}

这只是一个简单的例子。如果您可以注册ProcessorTransaction,那会更好。 E.g。

public void register(String processorType, Processor processor){
   ...
}
public void register(String transactionType, Transaction transaction){
   ...
}

你也可能想要使用花药类型然后String作为键,也许是枚举。

在此示例中,每次创建Processor时都会重复使用TransactionPaymentProcessor个对象。如果要为每个PaymentProcessor创建新对象,可以替换Map类型

private Map<String, Factory<Processor>> processorMap = new HashMap<>();
private Map<String, Factory<Transaction>> transactionMap = new HashMap<>();

使用花药工厂界面。 E.g。

public interface Factory<T> {
  public T newInstance();
}