简体   繁体   中英

Java - How to properly combine Abstract Factory with Factory method?

I looked at examples using abstract factory and factory methods. But how could I properly combine both, so abstract factory would choose which concrete factory is needed and factory method then would choose what to create in a given factory. I tried to make myself one program using these patterns, but got into dead end. Cant figure out how to properly combine both patterns to make my program work. My program is very simple. It would just create furniture - either tables or chairs, depending on concrete Factory chosen.

And then it would create round table or square table if Table Factory would be chosen (also writing type, either round or square). Then the same for Chair Factory if that factory would be chosen.

So my code looks like this (some parts may be incorrect as that's is why I'm asking this question):

package pack1;
//abstract product
public abstract class Table {
    protected final String name;
    public Table(String name) { 
        this.name = name;
    }
}

package pack1;
//concrete product
public class SquareTable extends Table {
    public SquareTable(String name) { 
        super(name);
    }

}

package pack1;
//concrete product
public class RoundTable extends Table {
    public RoundTable(String name) { 
        super(name);
    }
}

package pack1;
//abstract product
public abstract class Chair {
     protected final String name;
        public Chair(String name) { 
            this.name = name;
        }
}

package pack1;
//concrete product
public class WoodenChair extends Chair {
    public WoodenChair(String name) { 
        super(name);
    }
}

package pack1;
//concrete product
public class MetalChair extends Chair {
    public MetalChair(String name) { 
        super(name);
    }

}

package pack1;
//Abstract Factory
public interface AbstractFurnitureFactory {
    public Table createTable(String type, String name);
    //not finished. How to use different create methods for different factories,
    //so it wouldn't require to use this method in concrete factories or
    //do I need 2 concrete factories for this to work?..
}

package pack1;
//concrete factory
public class TableFactory implements AbstractFurnitureFactory {
    public Table createTable(String type, String name){ 
    if(type.equals("square"))                       
    { 
        SquareTable sq_table=new SquareTable(name);
        return sq_table;
     }
     else
    {
        RoundTable rn_table=new RoundTable(name);
        return rn_table;
    }
}

}

package pack1;
//concrete factory
public class ChairFactory {
    public Chair createChair(String type, String name){ 
        if(type.equals("wood"))                       
        { 
            WoodenChair wd_chair=new WoodenChair(name);
            return wd_chair;
         }
         else
        {
            MetalChair mt_chair=new MetalChair(name);
            return mt_chair;
        }
    }
}

package pack1;
//client
public class FurnitureBuilder {
    public void buildTable(AbstractFurnitureFactory tf)
       {
          //Table table = tf.createTable();   
          //table.name = "New table";
          //not Finished. Java won't let me set arguments in createTable 
          //method for example. It gives error - 'The method 
          //createTable(String, String) in the type 
          //AbstractFurnitureFactory is not applicable for the arguments ()'
       }

}

package pack1;

public class Main {
    public static void main(String[] args)   
    {
        //FurnitureBuilder builder = new FurnitureBuilder();
        //AbstractFurnitureFactory TableFactory = null;
        //Not finished as some parts are missing.

    }
}

So if anyone could pinpoint and/or fix what I am doing wrong, I would very much appreciate it.

I think you are confusing which factories should inherit from which abstract factory.

A better Factory design would be to have the same factory make different kinds of Tables or Chairs . This makes AbstractFurnitureFactory not needed.

For example :

  public interface TableFactory{

    Table createTable(String name);
  }


public class SquareTableFactory implements TableFactory{
    @Override
    Table createTable(String name){
          return new SquareTable(name);
    }
}

public class RoundTableFactory implements TableFactory{
    @Override
    Table createTable(String name){
          return new RoundTable(name);
    }
}

Then

public class FurnitureBuilder {
    private final TableFactory tf;
    private final ChairFactory cf;

    ...

   public void buildTable(String name){
      Table table = tf.createTable(name);
      ...
   }

}

Hope this makes things more clear.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM