Java 这是实现工厂方法设计模式的正确方法吗
我必须根据某些标准对不同的特许经营实施不同的收费结构。我为结构创建了一个抽象类Java 这是实现工厂方法设计模式的正确方法吗,java,design-patterns,factory,factory-pattern,Java,Design Patterns,Factory,Factory Pattern,我必须根据某些标准对不同的特许经营实施不同的收费结构。我为结构创建了一个抽象类 public abstract class FranchiseFeeStructure { private BigDecimal registrationFee=1500; protected BigDecimal monthlyFee; public BigDecimal getMonthlyFees(){ return monthlyF
public abstract class FranchiseFeeStructure {
private BigDecimal registrationFee=1500;
protected BigDecimal monthlyFee;
public BigDecimal getMonthlyFees(){
return monthlyFee;
}
public BigDecimal calculateFee{
//calculate fee here
return fee;
}
}
现在,对于不同的结构,我创建了一些类,这些类扩展了
public class ST1 extends FranchiseFeeStructure{
@Override
void getMonthlyFee(){
monthlyFee=890;
}
}
以及各种结构的ST2、ST3等。我们有一个类,有静态工厂方法
public class GetFeeStructureFactory {
public static FranchiseFeeStructure getFranchiseFeeStructure(String franchiseFeeStructureType){
if(franchiseFeeStructureType == null){
return null;
}
if(franchiseFeeStructureType.equalsIgnoreCase("ST1")) {
return new ST1();
}
else if(franchiseFeeStructureType.equalsIgnoreCase("ST2")){
/// so on...
}
}
现在把它当作
FranchiseFeeStructure franchiseFeeStructure = GetFeeStructureFactory.getFranchiseFeeStructure("ST1");
franchiseFeeStructure.getMonthlyFee();
franchiseFeeStructure.calculateFee();
这是实现方法工厂模式的正确方法吗。请告诉我我是否错了,或者是否有任何改进建议。工厂实施中的问题并非如此。这是抽象类的实现方式。它通过调用(名称不正确的)方法
getMonthlyFee()
,强制每个调用者初始化月费。打电话的人不应该这么做。您的抽象类应该依赖于。。。用一种抽象的方法来实现这一点:
public abstract class FranchiseFeeStructure {
private static final BigDecimal REGISTRATION_FEE = new BigDecimal(1500);
public final BigDecimal calculateFee {
BigDecimal monthlyFee = getMonthlyFee();
// TODO compute
return fee;
}
/**
* Subclasses must implement this method to tell what their monthly fee is
*/
protected abstract BigDecimal getMonthlyFee();
}
public class ST1 extends FranchiseFeeStructure {
@Override
protected BigDecimal getMonthlyFee(){
return new BigDecimal(890);
}
}
这样,呼叫者就不需要初始化月费。它所需要做的就是
BigDecimal fee = FeeStructureFactory.getFranchiseFeeStructure("ST1").calculateFee();
请注意,如果月费始终是一个常量,那么您甚至不需要一个抽象类和多个子类。你所需要的只是一个单独的类,将月费作为构造函数参数。是的,想法是一样的,但是你可以改进你的代码。我会根据自己的情况提出改进建议。我将为它提供一个接口和实现,而不是抽象类,但其思想是相同的
interface FranchiseFee{
BigDecimal getMonthlyFee();
BigDecimal calculateFee():
}
public class CocaColaFee implements FranchiseFee{
public BigDecimal getMonthlyFee(){
return new BigDecimal("..");
}
public BigDeicaml calculateFee(){
// do the calculation
}
}
public class PepsiFee implements FranchiseFee{
public BigDecimal getMonthlyFee(){
return new BigDecimal("..");
}
public BigDeicaml calculateFee(){
// do the calculation
}
}
public FranchiseFeeFactoty {
// this is the easiest way to avoid if/else which makes the code awful. Also to use this you need to have default constructor, because as you can see you need additional code and it get's complicated.
//the other way is to use map but it's just a more convenient if/else approach
public static FranchiseFee create(Class<? extends FranchiseFee> franchiseFeeType){
try {
return franchiseFeeType.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
接口费{
BigDecimal getMonthlyFee();
BigDecimal calculateFee():
}
公共级CocaColaFee实行特许经营费{
公共BigDecimal getMonthlyFee(){
返回新的BigDecimal(“..”);
}
公共Bigdecaml calculateFee(){
//计算
}
}
公共类百事可乐实行特许经营费{
公共BigDecimal getMonthlyFee(){
返回新的BigDecimal(“..”);
}
公共Bigdecaml calculateFee(){
//计算
}
}
公共特许经营权{
//这是避免if/else导致代码糟糕的最简单方法。同样,要使用它,您需要有默认构造函数,因为正如您所看到的,您需要额外的代码,而且它变得很复杂。
//另一种方法是使用map,但它只是一种更方便的if/else方法
公共静态特许经营费创建(类感谢Nizet,我真的很感谢你的回答。当然,我必须将getMonthlyFee作为抽象方法。但我无法理解作为构造函数参数的月费作为你的最后一行。在我的情况下,月费对于不同的费用结构是不同的,但如果每个子类的月费都是恒定的,你可以简单地将Fra作为nchiseFreeStructure不是抽象的,并且返回新的特许经营的Freestructure(890)
或返回新的特许经营的Freestructure(122)
取决于结构类型。不需要子类简单地更改值。子类对更改行为很有用,即提供不同的逻辑。如您所说,请注意,谢谢,但我有不同结构的各种变量及其行为,除了月费。如果调用方需要引用该类(例如,PepsiFee.class)为了获得实例,它可以直接调用构造函数。工厂的要点是从一些不相关的值(例如字符串)获取对象,不知道将收到哪种具体类型。我必须不同意,我不知道你的引用是什么意思。你可以引用一个对象,但无论如何。不,你不能,因为这样无论你做了多少个实现,你都不会在工厂方法中添加另一个愚蠢的if。如果你有10个实现呢tations?你将有一堆ifs来获取实例。同样,如果我在factory方法中更改字符串,而你过去常常从某个地方调用它,我可能会在不知情的情况下破坏你的代码。我想你不明白。假设你从网页收到某个JSON对象,而这个JSON对象包含字符串“coke”或“pepsi”。现在根据此字符串获取相应的免费实例。这就是OP尝试实现的工厂的全部要点。无论您以何种方式看待它,您都必须实现一些基于此字符串将返回相应实例的内容。不,JSON将不包含类的名称,因为utside world不需要关心应用程序的内部实现。