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不需要关心应用程序的内部实现。