简单工厂模式

任何可以产生对象的方法或类,都可以称之为工厂。单例也可以成为一种工厂。为什么可以new对象,还需要工厂?因为可以灵活控制生产过程。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

  1. 比如需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
  2. 简单工厂模式最大的优点在于实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责,
  3. 但是其最大的缺点在于工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,
  4. 而且产品较多时,工厂方法代码逻辑将会非常复杂。
  5. 比如像下面的代码,我想增加一个画平行四边形的,那么则有需要建一个类去实现Shape接口。扩展性差。

创建一个接口

  1. 形状类,里面有一个画画的方法
  2. public interface Shape {
  3. void draw();
  4. }

创建实现接口的实体类。

  1. 矩形类,实现了形状类,重写了画画方法,画出了一个矩形
  2. public class Rectangle implements Shape {
  3. @Override
  4. public void draw() {
  5. System.out.println("画出矩形::draw() method.");
  6. }
  7. }
  1. 方形类,实现了形状类,重写了画画方法,画出了一个方形
  2. public class Square implements Shape {
  3. @Override
  4. public void draw() {
  5. System.out.println("画出方形::draw() method.");
  6. }
  7. }
圆形类,实现了形状类,重写了画画方法,画出了一个圆形
public class Circle implements Shape {
   @Override
   public void draw() {
      System.out.println("画出圆形::draw() method.");
   }
}

创建一个工厂,生成基于给定信息的实体类的对象。

public class ShapeFactory {
   //使用 getShape 方法获取形状类型的对象
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }        
      //根据传入的形状类型,返回对应的类
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
}

使用该工厂,通过传递类型信息来获取实体类的对象。

public class FactoryPatternDemo {

   public static void main(String[] args) {
      ShapeFactory shapeFactory = new ShapeFactory();

      //获取 Circle 的对象,并调用它的 draw 方法
      Shape shape1 = shapeFactory.getShape("CIRCLE");

      //调用 Circle 的 draw 方法
      shape1.draw();

      //获取 Rectangle 的对象,并调用它的 draw 方法
      Shape shape2 = shapeFactory.getShape("RECTANGLE");

      //调用 Rectangle 的 draw 方法
      shape2.draw();

      //获取 Square 的对象,并调用它的 draw 方法
      Shape shape3 = shapeFactory.getShape("SQUARE");

      //调用 Square 的 draw 方法
      shape3.draw();
   }
}

工厂方法模式

是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,
则不能正确创建对象,而工厂方法模式是提供多个工厂方法,分别创建对象。
将上面的ShapeFactory形状工厂类,稍微改动一下。

public class ShapeFactory {
   //直接返回圆形类
   public Shape getCircleShape(){
       return new Circle();
   } 
   //直接返回矩形类
   public Shape getRectangleShape(){
       return new Rectangle();
   }
   //直接返回方形类
   public Shape getSquareShape(){
       return new Square();
   }
}

//测试
public class FactoryPatternDemo {
   public static void main(String[] args) {
      ShapeFactory shapeFactory = new ShapeFactory();
             Shape circle = shapeFactory.getCircleShape();
      //调用 Circle 的 draw 方法
      circle.draw();
   }
}

静态工厂方法模式

将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。
public class ShapeFactory {
   //直接返回圆形类
   public static Shape getCircleShape(){
       return new Circle();
   } 
   //直接返回矩形类
   public static Shape getRectangleShape(){
       return new Rectangle();
   }
   //直接返回方形类
   public static Shape getSquareShape(){
       return new Square();
   }
}

//测试
public class FactoryPatternDemo {
   public static void main(String[] args) {
             Shape circle = ShapeFactory.getCircleShape();
      //调用 Circle 的 draw 方法
      circle.draw();
   }
}

总体来说,工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。在以上的三种模式中,第一种如果传入的字符串有误,不能正确创建对象,第三种相对于第二种,不需要实例化工厂类,所以,大多数情况下,我们会选用第三种——静态工厂方法模式。

抽象工厂模式

工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,
必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?
就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,
不需要修改之前的代码。

创建一个接口

形状类,里面有一个画画的方法
public interface Shape {
   void draw();
}

创建实现接口的实体类。

矩形类,实现了形状类,重写了画画方法,画出了一个矩形
public class Rectangle implements Shape {
   @Override
   public void draw() {
      System.out.println("画出矩形::draw() method.");
   }
}
方形类,实现了形状类,重写了画画方法,画出了一个方形
public class Square implements Shape {
   @Override
   public void draw() {
      System.out.println("画出方形::draw() method.");
   }
}
圆形类,实现了形状类,重写了画画方法,画出了一个圆形
public class Circle implements Shape {
   @Override
   public void draw() {
      System.out.println("画出圆形::draw() method.");
   }
}

再创建一个接口,或者抽象类,这里以接口为例

public interface ShapeFactory {  
    public Shape shape();
}

创建对应的工厂类

实现上面的工厂类,并且重写方法
public class CircleFactory implements ShapeFactory{
   @Override  
    public Shape shape(){  
        return new Circle();  
    }  
}

public class RectangleFactory implements ShapeFactory{
   @Override  
    public Shape shape(){  
        return new Rectangle();  
    }  
}

public class SquareFactory implements ShapeFactory{
   @Override  
    public Shape shape(){  
        return new Square();  
    }
}

其实这个模式的好处就是,如果你现在想增加一个功能:比如画任意形状,则只需做一个实现类,实现Shape接口,同时做一个工厂类,实现ShapeFactory接口,就OK了,无需去改动现成的代码。这样做,拓展性较好!