抽象工厂:提供一系列相关或互相依赖对象的接口,而无须指定它们具体的类。
抽象工厂
例子:依旧是上篇博客中的例子,Beijing和Shanghai餐馆分别都有Eat和Drink两个方法,而Beijing和Shanghai属于不同的产品足族(它们都有自己的系列),所以此时可以使用抽象工厂模式。UML图如下:
抽象工厂类:创建访问对象的工厂接口
/*
* 抽象工厂类:Eat Drink两个不同方法
*/
public abstract class AbstractFactory {
public abstract Eat createRestaurantEat();
public abstract Drink createRestaurantDrink();
}
具体工厂类:Beijing或Shanghai
/*
* 具体创建对象的工厂
*/
public class RestaurantBeijing extends AbstractFactory {
@Override
public Eat createRestaurantEat() {
return new EatBeijing();
}
@Override
public Drink createRestaurantDrink() {
return new DrinkBeijing();
}
}
抽象类Eat:
/*
* Eat抽象类
*/
public abstract class Eat {
public abstract void eat();
}
Eat具体实现类:
/*
* Eat具体实现类
*/
public class EatBeijing extends Eat {
@Override
public void eat() {
System.out.println("在北京餐馆吃饭");
}
}
public class EatShanghai extends Eat {
@Override
public void eat() {
System.out.println("在上海餐馆吃饭");
}
}
Demo:创建实例,调用方法
public class demo {
public static void main(String[] args) {
//北京分店餐馆
//多态:创建工厂实现类
AbstractFactory abstractFactory=new RestaurantBeijing();
//多态:具体工厂实现类创建eat的具体实现
Eat createRestaurantEat = abstractFactory.createRestaurantEat();
//调用方法
createRestaurantEat.eat();
Drink createRestaurantDrink = abstractFactory.createRestaurantDrink();
createRestaurantDrink.drink();
}
}
控制台显示:
由此我们可以看到当出现不同的产品族、整体不同的系列时,抽象工厂就非常实用。
简单工厂改进抽象工厂
当我们需要在原有基础上增加新的功能如:唱歌时,需要修改的三个抽象类,这样就很复杂,所以可以使用简单工厂+抽象工厂进行改进。
抽象类Eat/Drink
/*
* 抽象类
*/
public abstract class Eat {
public abstract void eat();
}
抽象的具体实现类
/*
* 抽象的具体实现类
*/
public class EatBeijing extends Eat {
@Override
public void eat() {
System.out.println("在北京餐馆吃饭");
}
}
public class EatShanghai extends Eat {
@Override
public void eat() {
System.out.println("在上海餐馆吃饭");
}
}
抽象工厂+简单工厂:动态实例化对象
/*
* 抽象工厂+简单工厂
*/
public class SumFactory {
//可以从前台传参过来
private static String place="上海";
//吃
public static Eat createEat(){
Eat eat=null;
switch(place){
case "北京":
eat=new EatBeijing();
break;
case "上海":
eat=new EatShanghai();
break;
}
return eat;
}
//喝
public static Drink createDrink(){
Drink drink=null;
switch(place){
case "北京":
drink=new DrinkBeijing();
break;
case "上海":
drink=new DrinkShanghai();
break;
}
return drink;
}
}
Demo:创建实例,调用方法
public class demo {
public static void main(String[] args) {
//分店餐馆
Eat eat=SumFactory.createEat();
eat.eat();
Drink drink=SumFactory.createDrink();
drink.drink();
}
}
控制台显示
抽象工厂的优点是便于交换产品系列,让具体的创建实例过程与客户端分离,客户端是通过抽象接口操作实例,产品的具体类别也被具体工厂分离,遵循了开放-封闭和依赖倒转原则。
抽象工厂也可以应用于数据库的切换中,应用反射技术,动态获得类和对象,与配置文件的结合更加灵活应用。
抽象工厂的学习还在路上,走走停停,不断前进。