设计模式之抽象工厂

/ 设计模式 / 没有评论 / 320浏览

在上一篇中我们已“老王开车去东北”为需求介绍了设计模式中的简单工厂的使用。在这一篇我们还将已“老王开车去东北”为需求来介绍一下抽象工厂的使用。


下面我们将上面的需求修改一下然后我们通过新的需求在做详细分析。

需求:老王听着歌曲磕着瓜子开着汽车去东北。

按照我们简单工厂分析的那样,我们首先会抽象出歌曲类、瓜子类和汽车类,并抽象出它们每个类所特有的功能。下面我们每个类的源码。

Music:

/**
 * 抽象歌曲类
 */
public class Music {

    /**
     * 抽象听歌曲的方法
     */
    public void listen() {
        System.out.println("听着歌曲");
    }


}

MelonSeeds:

/**
 * 抽象瓜子类
 */
public class MelonSeeds {

    /**
     * 抽象吃的方法
     */
    public void eat() {
        System.out.println("吃瓜子");
    }


}

Car:

/**
 * 抽象汽车类
 */
public class Car {

    /**
     * 抽象去东北的方法
     */
    public void go() {
        System.out.println("开车去东北");
    }


}

Test:

/**
 * 测试类
 */
public class Test {

  public static void main(String[] args) {

    Music music = new Music();
    music.listen();

    MelonSeeds melonSeeds = new MelonSeeds();
    melonSeeds.eat();

    Car car = new Car();
    car.go();
  }
}

日志:

听着歌曲
吃瓜子
开车去东北

这样我们就基本实现了我们的需求了,但既然我们已经学了简单工厂模式那上面的代码明显不是方便扩展的,我们应该创建一个工厂类来提供对象的创建,而不应该用new关键字。下面为详细代码。

LaoWangFactory:

/**
 * 老王的工厂类
 */
public class LaoWangFactory {

  /**
   * 创建歌曲类
   */
  public Music createMusic() {
    return new Music();
  }

  /**
   * 创建瓜子类
   */
  public MelonSeeds createMelonSeeds() {
    return new MelonSeeds();
  }

  /**
   * 创建汽车类
   *
   * @return
   */
  public Car createCar() {
    return new Car();
  }

}

Test:

/**
 * 测试类
 */
public class Test {

  public static void main(String[] args) {

    LaoWangFactory laoWangFactory = new LaoWangFactory();

    Music music = laoWangFactory.createMusic();
    music.listen();

    MelonSeeds melonSeeds = laoWangFactory.createMelonSeeds();
    melonSeeds.eat();

    Car car = laoWangFactory.createCar();
    car.go();
  }
}

日志:

听着歌曲
吃瓜子
开车去东北

这样代码貌似没有问题了,但还有一个问题,就是程序还是不方便扩展的。因为如果需求改成“老李听着广播吃着苹果做着火车去东北”。那我们客户端的代码改动有多大呢?下面我们看一下详细代码。

Broadcast:

/**
 * 抽象广播类
 */
public class Broadcast {

    /**
     * 抽象听广播的方法
     */
    public void listen() {
        System.out.println("听着广播");
    }


}

Apple:

/**
 * 抽象苹果类
 */
public class Apple {

    /**
     * 抽象吃的方法
     */
    public void eat() {
        System.out.println("吃苹果");
    }


}

Train:

/**
 * 抽象火车类
 */
public class Train {

    /**
     * 抽象去东北的方法
     */
    public void go() {

        System.out.println("做火车去东北");
    }


}

LaoLiFactory:

/**
 * 老李的工厂类
 */
public class LaoLiFactory {

  /**
   * 创建广播类
   */
  public Broadcast createBroadcast() {
    return new Broadcast();
  }

  /**
   * 创建苹果类
   */
  public Apple createApple() {
    return new Apple();
  }

  /**
   * 创建火车类
   */
  public Train createTrain() {
    return new Train();
  }

}

Test:

/**
 * 测试类
 */
public class Test {

  public static void main(String[] args) {

//    LaoWangFactory laoWangFactory = new LaoWangFactory();
//
//    Music music = laoWangFactory.createMusic();
//    music.listen();
//
//    MelonSeeds melonSeeds = laoWangFactory.createMelonSeeds();
//    melonSeeds.eat();
//
//    Car car = laoWangFactory.createCar();
//    car.go();

    LaoLiFactory laoLiFactory = new LaoLiFactory();

    Broadcast broadcast = laoLiFactory.createBroadcast();
    broadcast.listen();

    Apple apple = laoLiFactory.createApple();
    apple.eat();

    Train train = laoLiFactory.createTrain();
    train.go();

  }
}

日志:

听着广播
吃苹果
做火车去东北

我们看日志虽然实现了需求,但因为不同的工厂类返回的对象是不同的,除此之外,不同的对象里面的方法也有可能是不同的,所以客户端的代码改动量非常大,这显示是不合理的。那怎么解决呢?答案还是和上一篇中的简单工厂模式一样,也就是多态。由于我们已经介绍过简单工厂模式了,所以在这里我们就不做过多的分析了,直接采用多态方式修改我们的代码。既然是多态那我们就要创建父子类了。通过分析我们知道,为了保证不同工厂的统一,所以我们会创建一个统一的工厂类,又因为不同工厂创建的对象可能是不同的,为了保证统一工厂返回的对象类型相同,所以我们还要抽象出不同对象工厂的统一对象的父类。下面为具体的源码。

Recreation:

/**
 * 抽象娱乐接口
 */
public interface Recreation {

  /**
   * 抽象听方法
   */
  void listen();
}

Food:

/**
 * 抽象食物接口
 */
public interface Food {

  /**
   * 抽象吃方法
   */
  void eat();
}

Vehicle:

/**
 * 抽象交通工具接口
 */
public interface Vehicle {

  /**
   * 抽象去东北的方法
   */
  void go();
}

Music:

/**
 * 抽象歌曲类
 */
public class Music implements Recreation {

    /**
     * 抽象听歌曲的方法
     */
    public void listen() {
        System.out.println("听着歌曲");
    }


}

Broadcast:

/**
 * 抽象广播类
 */
public class Broadcast implements Recreation {

    /**
     * 抽象听广播的方法
     */
    public void listen() {
        System.out.println("听着广播");
    }


}

MelonSeeds:

/**
 * 抽象瓜子类
 */
public class MelonSeeds implements Food {

    /**
     * 抽象吃的方法
     */
    public void eat() {
        System.out.println("吃瓜子");
    }


}

Apple:

/**
 * 抽象苹果类
 */
public class Apple implements Food{

    /**
     * 抽象吃的方法
     */
    public void eat() {
        System.out.println("吃苹果");
    }


}

Car:

/**
 * 抽象汽车类
 */
public class Car implements Vehicle {

    /**
     * 抽象去东北的方法
     */
    public void go() {
        System.out.println("开车去东北");
    }


}

Train:

/**
 * 抽象火车类
 */
public class Train implements Vehicle {

    /**
     * 抽象去东北的方法
     */
    public void go() {

        System.out.println("做火车去东北");
    }


}

AbstractFactory:

/**
 * 抽象出统一的工厂
 */
public interface AbstractFactory {

  /**
   * 创建娱乐类
   */
  Recreation createRecreation();

  /**
   * 创建食物类
   */
  Food createFood();

  /**
   * 创建交通工具类
   */
  Vehicle createVehicle();

}

LaoLiFactory:

/**
 * 老李的工厂类
 */
public class LaoLiFactory implements AbstractFactory {

  /**
   * 创建广播类
   */
  public Recreation createRecreation() {
    return new Broadcast();
  }


  /**
   * 创建苹果类
   */
  public Food createFood() {
    return new Apple();
  }


  /**
   * 创建火车类
   */
  public Vehicle createVehicle() {
    return new Train();
  }

}

LaoWangFactory:

/**
 * 老王的工厂类
 */
public class LaoWangFactory implements AbstractFactory {

  /**
   * 创建歌曲类
   */
  public Recreation createRecreation() {
    return new Music();
  }

  /**
   * 创建瓜子类
   */
  public Food createFood() {
    return new MelonSeeds();
  }

  /**
   * 创建汽车类
   *
   * @return
   */
  public Vehicle createVehicle() {
    return new Car();
  }


}

Test

/**
 * 测试类
 */
public class Test {

  public static void main(String[] args) {

    AbstractFactory factory = new LaoWangFactory(); //new LaoLiFactory();

    Recreation recreation = factory.createRecreation();
    recreation.listen();

    Food food = factory.createFood();
    food.eat();

    Vehicle vehicle = factory.createVehicle();
    vehicle.go();

  }
}

日志:

听着歌曲
吃瓜子
开车去东北

这样当我们想换实现时,只需要换另一个工厂即可。上述内容就是设计模式中抽象工厂的使用,如有不正确的地方,欢迎留言。下面链接为项目源码。

项目源码