模式概述:
能创建一系列相关的对象, 而无需指定其具体类。
使用场景:
1.如果代码需要与多个不同系列的相关产品交互, 但是由于无法提前获取相关信息, 或者出于对未来扩展性的考虑, 你不希望代码基于产品的具体类进行构建, 在这种情况下, 你可以使用抽象工厂。
2.如果你有一个基于一组抽象方法的类, 且其主要功能因此变得不明确, 那么在这种情况下可以考虑使用抽象工厂模式。
代码样例:
/**
* 食物基类(产品A)
*/
public abstract class Food {
public String foodName;
public abstract String getFoodName ();
}
/**
* 现代食物(具体产品A)
*/
public class ModernFood extends Food {
public ModernFood(){
foodName = "面包";
}
@Override
public String getFoodName() {
return foodName;
}
}
/**
* 远古食物(具体产品A)
*/
public class AncientFood extends Food{
public AncientFood(){
foodName="五谷";
}
@Override
public String getFoodName() {
return foodName;
}
}
/**
* 玩耍基类(产品B)
*/
public interface Game {
public void play();
}
/**
* 现代游戏(具体产品B)
*/
public class ModernGame implements Game{
@Override
public void play() {
System.out.println("现代人玩电子游戏。。。");
}
}
/**
* 远古游戏(具体产品B)
*/
public class AncientGame implements Game{
@Override
public void play() {
System.out.println("远古人没有游戏可以玩");
}
}
/**
* 人基类(产品C)
*/
public abstract class Person {
public abstract void eat(Food food);
public abstract void play(Game game);
}
/**
* 现代人(具体产品C)
*/
public class ModernPerson extends Person{
@Override
public void eat(Food food) {
System.out.println("现代人的食物是:"+food.getFoodName());
}
@Override
public void play(Game game) {
game.play();
}
}
/**
* 远古人(具体产品C)
*/
public class AncientPerson extends Person{
@Override
public void eat(Food food) {
System.out.println("远古人的食物:"+food.getFoodName());
}
@Override
public void play(Game game) {
game.play();
}
}
/**
* 抽象工厂
*/
public interface Factory {
Food createFood();
Game createGame();
Person createPerson();
}
/**
* 现代工厂
*/
public class ModernFactory implements Factory{
@Override
public Food createFood() {
return new ModernFood();
}
@Override
public Game createGame() {
return new ModernGame();
}
@Override
public Person createPerson() {
return new ModernPerson();
}
}
/**
* 远古工厂
*/
public class AncientFactory implements Factory{
@Override
public Food createFood() {
return new AncientFood();
}
@Override
public Game createGame() {
return new AncientGame();
}
@Override
public Person createPerson() {
return new AncientPerson();
}
}
/**
* 应用
*/
public class Application {
private Food food;
private Game game;
private Person person;
public Application(Factory factory){
this.food = factory.createFood();
this.game = factory.createGame();
this.person = factory.createPerson();
}
public void life(){
person.eat(food);
person.play(game);
}
}
public class TestAbstractFactory {
public static void main(String[] args) {
Application application= new Application(new ModernFactory());
application.life();
}
}
测试结果:
工厂方法与抽象工厂关系:
工厂方法是抽象工厂的特例,工厂方法只有一种产品,抽象工厂是一类的多种产品; 其中,工厂方法对外提供的功能接口是放在工厂基类中的,抽象工厂是把对外提供的功能接口提出来放到了application中,这块没有特别要求,设计是灵活的,把工厂方法中对外提供的功能接口也提取出来也是可以的,如果提取出来的话就更接近抽象工厂了。对于抽象工厂,工厂维度的扩展是简单的,比如此例中可以在扩展一个未来工厂,新增对应的未来工厂、未来人、未来食物、未来游戏即可;但是产品维度的扩展是复杂 的,比如要在工厂中扩一个产品Work,那么需要在工厂基类中添加,之后所有具体工厂都需要添加;同样的问题对于工厂方法,因一个工厂只有一个产品,所以扩展都是简单的。
附:
工厂方法链接:https://blog.youkuaiyun.com/weixin_38608005/article/details/117266854
设计模式链接:https://blog.youkuaiyun.com/weixin_38608005/article/details/117200828