使用场景
一个对象族有相同的约束时可以使用此模式。
例如:Android、iOS 都有短信软件和拨号软件,但是具体代码的实现逻辑不不一样,这个时候可以考虑使用抽象工厂模式来生产 Android、iOS 下的短信软件和拨号软件。
主要角色
AbstractFactory:抽象工厂角色。对应 AbstractFactory。
ConcreteFactory:具体工厂角色。对应 ConcreteFactory1 和 ConcreteFactory2。
AbstractProduct:抽象产品角色。对应 AbstractProductA 和 AbstractProductB。
ConcreteProduct:具体产品角色。对应 ConcreteProductA1、ConcreteProductA2、 ConcreteProductB1、ConcreteProductB2。
示例代码:
抽象产品类A
public abstract class AbstractProductA {
/**
* 每个具体的产品子类需要实现的方法
*/
public abstract void method();
}
抽象产品类B
public abstract class AbstractProductB {
/**
* 每个具体的产品子类需要实现的方法
*/
public abstract void method();
}
具体产品类A1
public class ConcreteProductA1 extends AbstractProductA {
@Override
public void method() {
System.out.println("具体产品A1的方法");
}
}
具体产品类A2
public class ConcreteProductA2 extends AbstractProductA {
@Override
public void method() {
System.out.println("具体产品A2的方法");
}
}
具体产品类B1
public class ConcreteProductB1 extends AbstractProductB {
@Override
public void method() {
System.out.println("具体产品B1的方法");
}
}
具体产品类B2
public class ConcreteProductB2 extends AbstractProductB {
@Override
public void method() {
System.out.println("具体产品B2的方法");
}
}
抽象工厂类
public abstract class AbstractFactory {
/**
* 创建产品A的方法
*/
public abstract AbstractProductA createProductA();
/**
* 创建产品B的方法
*/
public abstract AbstractProductB createProductB();
}
具体工厂1
public class ConcreteFactory1 extends AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB1();
}
}
具体工厂2
public class ConcreteFactory2 extends AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB2();
}
}
简单实现
需求:小明的车厂需要生产Q3、Q7两种类型的汽车,但是它们的零部件差别比较大。比如轮胎、发动机、制动系统。
-
轮胎相关类
public interface ITire { /** * 轮胎 */ void tire(); } public class NormalTire implements ITire { @Override public void tire() { System.out.println("普通轮胎"); } } public class SUVTire implements ITire { @Override public void tire() { System.out.println("越野轮胎"); } }
-
发动机相关类
public interface IEngine { /** * 发动机 */ void engine(); } public class DomesticEngine implements IEngine { @Override public void engine() { System.out.println("国产发动机"); } } public class ImportEngine implements IEngine { @Override public void engine() { System.out.println("进口发动机"); } }
-
制动系统相关类
public interface IBrake { void brake(); } public class NormalBrake implements IBrake { @Override public void brake() { System.out.println("普通制动"); } } public class SeniorBrake implements IBrake { @Override public void brake() { System.out.println("高级制动"); } }
-
抽象车厂类
public abstract class CarFactory { /** * 生产轮胎 */ public abstract ITire createTire(); /** * 生产发动机 */ public abstract IEngine createEngine(); /** * 生产制动系统 */ public abstract IBrake createBrake(); }
-
Q3 工厂类
public class Q3Factory extends CarFactory { @Override public ITire createTire() { return new NormalTire(); } @Override public IEngine createEngine() { return new DomesticEngine(); } @Override public IBrake createBrake() { return new NormalBrake(); } }
-
Q7 工厂类
public class Q7Factory extends CarFactory { @Override public ITire createTire() { return new SUVTire(); } @Override public IEngine createEngine() { return new ImportEngine(); } @Override public IBrake createBrake() { return new SeniorBrake(); } }
-
测试
public class Client { public static void main(String[] args) { Q3Factory factoryQ3 = new Q3Factory(); factoryQ3.createTire().tire(); factoryQ3.createEngine().engine(); factoryQ3.createBrake().brake(); System.out.println("-----------------"); Q7Factory factoryQ7 = new Q7Factory(); factoryQ7.createTire().tire(); factoryQ7.createEngine().engine(); factoryQ7.createBrake().brake(); } }
输出结果如下:
普通轮胎 国产发动机 普通制动 ----------------- 越野轮胎 进口发动机 高级制动
这里只有Q3 和Q7 的工厂,如果需要增加Q5的工厂,那么需要增加响应的类文件,这样会造成类文件非常多。因此,在开发中需要权衡慎用。
Android 源码中的实现
相对较少。Android 底层 MediaPlayer 的创建。
总结
-
优点:
分离接口与实现,客户端使用抽象工厂来创建需要的对象,而客户端无需知道具体的实现类是哪个,使其实现面向接口编程,使得该模式在切换产品类时更加灵活、容易。
-
缺点:
- 类文件陡增;
- 不太容易扩展新的产品类,因为每当增加一个产品类就需要修改工厂,那么所有的具体工厂类均会被修改。
所以其在实际开发中使用较少,了解即可。