计模式-创建型-抽象工厂模式

  创建型-抽象工厂模式

  前面已经说过工厂模式,工厂可以生产一类产品,即用工厂类创建所需的对象。

  现在假设我们有一个超级工厂,这个超级工厂包含多个小工厂,每个小工厂所生产的产品类型不一样。(这个超级工厂就是一个抽象工厂,它可以生产不同类的产品)

  抽象工厂怎样实现呢,下面我们说明一下:

  类图:

  类图会在后续补上,现在暂时没画

  本文引用W3Cschool中的java教程中设计模式,链接地址https://www.w3cschool.cn/java/java-abstract-factory-pattern.html

  假设我们现在不止要做创建外形Shape,我们也要创建打印机Printer。

  和工厂模式一样,创建外形Shape和他们的实现类:

  Shape.java

  

  public interface Shape {

     void draw();

  }

  不同类型的外形对象,即Shape接口的实现类

  Rectangle.java

public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Inside Rectangle::draw() method.");
        
    }
}

  Square.java

public class Square implements Shape {

    @Override
    public void draw() {
        System.out.println("Inside Square::draw() method.");
        
    }

}

  此时,我们再创建打印机Printer和它的实现类

  Printer.java

public interface Printer {
    void print();
}

  不同类型的打印机对象,即Printer接口的实现类

  PaperPrinter.java

public class PaperPrinter implements Printer{
    @Override
    public void print() {
       System.out.println("paper");
    }
}

  WebPrinter.java

public class WebPrinter implements Printer {
    @Override
    public void print() {
       System.out.println("web");
    }
}

  ScreenPrinter.java

public class ScreenPrinter implements Printer{
    @Override
    public void print() {
       System.out.println("screen");
    }
}

  现在我们创建一个超级工厂,最终结果是让他既能生产外形Shape,也能生产打印机Printer。

  AbstractFactory.java

public interface AbstractFactory {
    abstract Printer getPrinter(String type);
    abstract Shape getShape(String shape) ;
}

  现在再建设一些小工厂。在编程上,小工厂为超级工厂接口的实现类。

  ShapeFactory.java

public class ShapeFactory implements AbstractFactory{
       @Override
       public Shape getShape(String shapeType){
          if(shapeType == null){
             return null;
          }    
          if(shapeType.equalsIgnoreCase("RECTANGLE")){
             return new Rectangle();
          } else if(shapeType.equalsIgnoreCase("SQUARE")){
             return new Square();
          }
          return null;
       }
       
       @Override
       public Printer getPrinter(String type) {
          return null;
       }
}

  PrinterFactory.java

public class PrinterFactory implements AbstractFactory{
       @Override
       public Shape getShape(String shapeType){
          return null;
       }
       
       @Override
       public Printer getPrinter(String type) {
       if(type == null){
          return null;
        }    
      if(type.equalsIgnoreCase("paper")){
          return new PaperPrinter();
      } else if(type.equalsIgnoreCase("web")){
          return new WebPrinter();
      } else if(type.equalsIgnoreCase("Screen")){
          return new ScreenPrinter();
      }
      return null;
     }
}

  到现在,其实抽象工厂模式已经写完了。

  个人的感觉是,所谓设计模式,其实是一种编程习惯。为什么会有这种编程,肯定是编程是进行程序变动时吃过亏,所以有这种习惯。

  大家在进行抽象工厂设计时,其实就是一个大工厂(AbstractFactory抽象类),有一些小工厂(AbstractFactory抽象类的具体实现),小工厂进行对象的创建。

  至于具体的代码实现,比如说小工厂(AbstractFactory抽象类的具体实现)到底是怎样实现的,其实没有一个绝对的编程方式。

  本文中PrinterFactory.java工厂能根据getShape(String shapeType)中传递的shapeType参数,返回对应的实际外形shape的实现(即小工厂生产的外形),但根据getPrinter(String type)方法,都返回空。此时我们根据是外形Shape或者打印机Printer来建设不同的工厂PrinterFactory.java和PrinterFactory.java。其实我们也可以根据其他方式来区分不同的工厂,创建不同的工厂对象。在新创建的工厂中,getShape和getPrinter方法返回的结果也可以都不为空。这个根据需要也可以进行新工厂的创建。甚至于小工厂(如PrinterFactory.java)中根据传入参数,返回不同对象,也可以换成其他方式,如不同方法名称放回不同对象等,本文中就不做过多的描述(理解了就好,写多了,搞得就像这个东西好复杂一样,其实不然)。

  至于使用,示例如下:

  AbstractFactoryTest.java

public class AbstractFactoryTest {
       public static void main(String[] args) {
           //get shape factory
           AbstractFactory shapeFactory = (AbstractFactory) new ShapeFactory();

           //get an object of Shape Circle
           Shape shape1 = shapeFactory.getShape("SQUARE");

           //call draw method of Shape Circle
           shape1.draw();;

           //get an object of Shape Rectangle
           Shape shape2 = shapeFactory.getShape("RECTANGLE");

           //call draw method of Shape Rectangle
           shape2.draw();
              

           //get printer factory
           AbstractFactory printerFactory = (PrinterFactory) new PrinterFactory();

           Printer printer1 = printerFactory.getPrinter("paper");
           printer1.print();
           Printer printer2 = printerFactory.getPrinter("Web");
           printer2.print();
           Printer printer3 = printerFactory.getPrinter("Screen");
           printer3.print();
     }
}

  运行结果

Inside Square::draw() method.
Inside Rectangle::draw() method.
paper
web
screen

  当然,根据面向对象的思维方式,也可以创建一个使用Factory生成器/生产器类,通过传递Shape或Printer等信息来获取工厂。

 FactoryProducer.java

public class FactoryProducer {
    public static AbstractFactory getFactory(String choice){
          if(choice.equalsIgnoreCase("SHAPE")){
             return new ShapeFactory();
          } else if(choice.equalsIgnoreCase("Printer")){
             return new PrinterFactory();
          }
          return null;
    }
}

运用时:

AbstractFactoryPackTest.java
public class AbstractFactoryPackTest {
    public static void main(String[] args) {

          //get shape factory
          AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");

          //get an object of Shape Rectangle
          Shape shape2 = shapeFactory.getShape("RECTANGLE");

          //call draw method of Shape Rectangle
          shape2.draw();
          
          //get an object of Shape Square 
          Shape shape3 = shapeFactory.getShape("SQUARE");

          //call draw method of Shape Square
          shape3.draw();

          //get printer factory
          AbstractFactory printerFactory = FactoryProducer.getFactory("printer");

        Printer printer1 = printerFactory.getPrinter("Paper");
        printer1.print();
        Printer printer2 = printerFactory.getPrinter("Web");
        printer2.print();
        Printer printer3 = printerFactory.getPrinter("Screen");
        printer3.print();
       }
}

运行结果:

Inside Rectangle::draw() method.
Inside Square::draw() method.
paper
web
screen

 从类图看,其实工厂模式和抽象工厂都差不多,不过工厂模式生产一类产品,而抽象工厂模式相当于一个大工厂,可以生产不同类的产品。

猜你喜欢

转载自www.cnblogs.com/sxrtb/p/10877164.html