设计模式-工厂设计模式

背景:

在Java中,万物皆对象。要想使用这些对象,就需要创建它,如果在使用该对象的类中都采用new方式创建该对象,会严重耦合,假如要更换对象,所以new该对象的地方都要做修改,这违背了软件的开闭设计原则。
如果使用工厂来生产对象,就只和工厂打交道了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦

工厂设计模式解决的问题:

在系统重构或增加产品时类的建立,如果类的建立放在主逻辑中。会导致修改工作量大而且在分工合作时代码结构化变差、书写难度增加、代码通用性变差
工厂设计模式属于创建型设计模式中的一种,他提供了创建对象的最佳方式。
 
简单工厂案例:
先将产品类抽象出来,比如,苹果和梨都属于水果,抽象出来一个水果类Fruit,苹果和梨就是具体的产品类,然后创建一个水果工厂,分别用来创建苹果和梨;代码如下:
水果接口
public interface IFruit {
    void get();
}
苹果
public class Apple implements IFruit {
    @Override
    public void get() {
        System.out.println(“apple”);
    }
}

 梨

public class Pear implements Fruit {
    @Override
    public void get() {
         System.out.println(“pear”);
    }
}
水果工厂

public class FruitFactory {
    public Fruit createFruit(String type) {

        if (type.equals("apple")) {//生产苹果
            return new Apple();
        } else if (type.equals("pear")) {//生产梨
            return new Pear();
        }
        return null;
    }
}
使用:
FruitFactory factory = new FruitFactory();
Apple apple = (Apple) factory.createFruit("apple");//获得苹果
Pear pear = (Pear) factory.createFruit("pear");//获得梨
一个非常简单的工厂设计模式就完成了。
 
那么问题来了,我想吃桃子、香蕉,我还想吃其他的水果,那不是都得创建桃子、香蕉、等等其他水果实现IFruit接口,然后在FruitFactory的createFruit修改添加创建桃子、香蕉等代码。显然,每当需要添加一种水果的时候,就需要修改工厂类,这显然违背了开闭原则。
所以简单工厂只适合于产品对象较少,且产品固定的需求,对于产品变化无常的需求来说显然不合适。
 
工厂方法设计模式:
将工厂提取成一个接口或抽象类,具体生产什么产品由子类决定
 
工厂接口
public interface FruitFactory {
    Fruit createFruit();//生产水果
}
苹果工厂
public class AppleFactory implements FruitFactory {
    @Override
    public Fruit createFruit() {
        return new Apple();
    }
}
梨工厂

public class PearFactory implements FruitFactory {
    @Override
    public Fruit createFruit() {
        return new Pear();
    }
}
使用

AppleFactory appleFactory = new AppleFactory();//创建苹果工厂
PearFactory pearFactory = new PearFactory();//创建梨工厂
Apple apple = (Apple) appleFactory.createFruit();//获得苹果
Pear pear = (Pear) pearFactory.createFruit();//获得梨
以上这种方式,虽然解耦了,也遵循了开闭原则,问题根本还是没有解决,如果需要的产品很多的话,需要创建非常多的工厂,所以这种方式的缺点也很明显
 
抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象

 

 

代码实现:

1)为形状创建一个接口
Shape.java
public interface Shape {
   void draw();
}
2)创建具体形状类,实现形状接口
Rectangle.java
public class Rectangle implements Shape {
   @Override
   public void draw() {
      System.out.println("Rectangle");
   }
}
Square.java
public class Square implements Shape {
   @Override
   public void draw() {
      System.out.println("Square ");
   }
}
3)为颜色创建一个接口
Color.java
public interface Color{
   void fill();
}
4)创建具体颜色类,实现颜色接口
Red.java
public class Red implements Color{
    @Override
   public void fill() {
      System.out.println("Red");
   }
}
Blue.java
public class Blueimplements Color{
    @Override
   public void fill() {
      System.out.println("Blue");
   }
}
5)为 Color 和 Shape 对象创建抽象类来获取工厂
AbstractFactory.java
public abstract class AbstractFactory {
   public abstract Color getColor(String color);
   public abstract Shape getShape(String shape) ;
}
6)创建Color和Shape 对应的工厂,都集成AbstractFactory
//ShapeFactory生产shape
 public class ShapeFactory extends  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 Color getColor(String color) {
      return null;
   }
}
//ColorFactory生产color
 public class ColorFactory  extends  AbstractFactory{
   @Override
   public Shape getShape(String shapeType){
      return null;
   }
   
   @Override
   public Color getColor(String color) {
      if(color == null){
         return null;
      }        
      if(color.equalsIgnoreCase("RED")){
         return new Red();
      }else if(color.equalsIgnoreCase("BLUE")){
         return new Blue();
      }
      return null;
   }
}
7)创建一个工厂创造器/生成器类,通过传递形状或颜色信息来获取工厂
public class FactoryProducer {
   public static AbstractFactory getFactory(String choice){
      if(choice.equalsIgnoreCase("SHAPE")){
         return new ShapeFactory();
      } else if(choice.equalsIgnoreCase("COLOR")){
         return new ColorFactory();
      }
      return null;
   }
}
8)使用 FactoryProducer 来获取 AbstractFactory,通过传递类型信息来获取实体类的对象
public class AbstractFactoryPatternDemo {
   public static void main(String[] args) {
      //获取形状工厂
      AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");

      //获取形状为 Square的对象
      Shape shape1 = shapeFactory.getShape("SQUARE");
 
      //调用 Square的 draw 方法
      shape1.draw();
 
      //获取形状为 Rectangle 的对象
      Shape shape2 = shapeFactory.getShape("RECTANGLE");
 
      //调用 Rectangle 的 draw 方法
      shape2.draw();
      
    
      //获取颜色工厂
      AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
 
      //获取颜色为 Red 的对象
      Color color1 = colorFactory.getColor("RED");
 
      //调用 Red 的 fill 方法
      color1.fill();
 
      //获取颜色为 Blue 的对象
      Color color2 = colorFactory.getColor("BLUE");
 
      //调用 Green 的 fill 方法
      color2.fill();
 
   }
}
三种工厂方式总结:
1、对于简单工厂和工厂方法来说,两者的使用方式实际上是一样的,如果对于产品的分类和名称是确定的,数量是相对固定的,推荐使用简单工厂模式;
2、抽象工厂用来解决相对复杂的问题,适用于一系列、大批量的对象生产;

posted @ 2020-09-13 21:54  楔子  阅读(208)  评论(0)    收藏  举报