顿搜
抽象工厂模式——23种设计模式之创建型模式
一、问题提出
一个电器工厂可以产生多种类型的电器,如海尔工厂可以生产海尔电视机、海尔空调等,TCL工厂可以生产TCL电视机、TCL空调等,相同品牌的电器构成一 个产品族,而相同类型的电器构成了一个产品等级结构。如何使用工厂模式创建对应的产品。会发现,相同产品分为了两家生产,显然工厂方法模式不在适用。
- ①、产品等级结构:产品等级结构即产品的继承结构。,抽象电视机是父类,而具体品牌的电视机是其子类。
- ②、产品族:产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,
二、抽象工厂模式
抽象工厂模式就是针对多套相似业务逻辑或多种相似产品相关类的实例的创建工作,整合了多种相同或相似的业务系统的解决方案!
定义一个接口用于创建相关或有依赖关系的对象族,即提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类,客户端不必指定产品的具体类型,创建多个产品族中的产品对象。
抽象工厂模式是对象的创建模式,是工厂方法模式的进一步推广。假设一个子系统需要一些产品对象,而这些产品对象又属于一个以上的产品等级结构。那么为了将消费这些产品对象的责任和创建这些产品对象的责任分割开来,可以 引进抽象工厂模式。使得消费产品的一方不需要直接参与产品的创建工作,而只需要向一个公用的工厂接口请求所需要的产品。
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。
运用抽象工厂模式的关键点在于应对“多系列对象创建”的需求变化。
三、与工厂方法模式的比较
- ①、工厂方法模式针对的是一个产品等级结构。
- ②、抽象工厂模式需要面对多个产品等级结构。
四、类图表示
抽象工厂模式涉及抽象工厂角色(AbstractFactory)、具体工厂角色(ConcreteFactory)、抽象产品角色(AbstractProduct)及具体产品角色(ConcreteProduct)等角色。
- ①、抽象工厂角色:声明创建抽象产品对象的接口。
- ②、具体工厂角色:实现创建具体产品对象的操作。
- ③、抽象产品角色:为一种产品对象声明一个接口。
- ④、具体产品角色:定义将被相应的具体工厂创建的产品对象。实现抽象产品角色接口。
- ⑤、用户:仅使用由AbstractFactory和AbstractProduct类声明的接口。
五、代码示例
//抽象产品(Benz)
abstract class BenzCar{
private String name;
public abstract void drive();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}//具体产品(Benz品牌的Sport和Business两种类型车)
class BenzSportCar extends BenzCar{
public void drive(){
System.out.println(this.getName()+"----BenzSportCar-----------------------");
}
}
class BenzBusinessCar extends BenzCar{
public void drive(){
System.out.println(this.getName()+"----BenzBusinessCar-----------------------");
}
}//抽象产品(Bmw)
abstract class BmwCar{
private String name;
public abstract void drive();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}//具体产品(Bmw品牌的Sport和Business两种类型车)
class BmwSportCar extends BmwCar{
public void drive(){
System.out.println(this.getName()+"----BmwSportCar-----------------------");
}
}
class BmwBusinessCar extends BmwCar{
public void drive(){
System.out.println(this.getName()+"----BmwBusinessCar-----------------------");
}
}//抽象产品(Audi)
abstract class AudiCar{
private String name;
public abstract void drive();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}//具体产品(Audi品牌的Sport和Business两种类型车)
class AudiSportCar extends AudiCar{
public void drive(){
System.out.println(this.getName()+"----AudiSportCar-----------------------");
}
}
class AudiBusinessCar extends AudiCar{
public void drive(){
System.out.println(this.getName()+"----AudiBusinessCar-----------------------");
}
}//抽象工厂
abstract class Driver{
public abstract BenzCar createBenzCar(String car) throws Exception;
public abstract BmwCar createBmwCar(String car) throws Exception;
public abstract AudiCar createAudiCar(String car) throws Exception;
}//具体工厂(Sport类型)
class SportDriver extends Driver{
public BenzCar createBenzCar(String car) throws Exception {
return new BenzSportCar();
}
public BmwCar createBmwCar(String car) throws Exception {
return new BmwSportCar();
}
public AudiCar createAudiCar(String car) throws Exception {
return new AudiSportCar();
}
}//具体产品(Business类型)
class BusinessDriver extends Driver3{
public BenzCar createBenzCar(String car) throws Exception {
return new BenzBusinessCar();
}
public BmwCar createBmwCar(String car) throws Exception {
return new BmwBusinessCar();
}
public AudiCar createAudiCar(String car) throws Exception {
return new AudiBusinessCar();
}
}//测试
public class Test{
public static void main(String[] args) throws Exception {
Driver d = new BusinessDriver();
AudiCar car = d.createAudiCar("myCar");
car.drive();
}
}六、优缺点分析
1、优点
- ①、分离了具体的类,一个工厂封装创建产品对象的责任和过程,它将客户与类的实现分离
- ②、易于交换产品系列,只需改变具体的工厂就可以使用不同的产品配置。
- ③、有利于产品一致性,当一个系列中的产品对象一起工作时,一个应用一次只能使用同一个系列中的对象。
2、缺点
- ①、难以支持新的产品等级结构(AbstractProductX),支持新的产品等级结构就要扩展抽象工厂接口。
七、特点
抽象工厂模式以一种倾斜的方式支持增加新的产品,为新产品族的增加提供方便,而不能为新的产品等级结构的增加提供这样的方便。
- ①、增加新的产品族:只需向系统中加入新的具体工厂类就能可以了,符合“开-闭”原则。
- ②、增加新的产品等级结构:需要修改所有的工厂角色,违背“开-闭”原则。
八、适用场景
抽象工厂模式最早的应用是用来创建在不同操作系统的视窗环境下都能运行的系统。如在Windows与Unix系统下都有视窗环境的构件,在每一个操作系统中,都有一个视窗构件组成的构件家族。
- ①、一个系统不依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都很重要
- ②、该系统的产品有多于一个的产品族,而系统只消费其中某一族的产品;(原始用意)
- ③、同属于同一产品族的产品是在一起使用的,这一约束条件必须在系统的设计中体现出来。
- ④、系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
九、改进方案
为了解决增加新的产品等级结构,需要修改所有的工厂角色,违背“开-闭”原则的问题,我们可以用简单工厂配合反射来改进抽象工厂。
// 简单工厂通过反射改进抽象工厂及其子工厂
class Driver{
public static BenzCar createBenzCar(String car) throws Exception {
return (BenzCar) Class.forName(car).newInstance();
}
public static BmwCar createBmwCar(String car) throws Exception {
return (BmwCar) Class.forName(car).newInstance();
}
public static AudiCar createAudiCar(String car) throws Exception {
return (AudiCar) Class.forName(car).newInstance();
}
}public class Test{
public static void main(String[] args) throws Exception {
AudiCar car = Driver.createAudiCar("com.java.pattendesign.factory.AudiSportCar");
car.drive();
}
}

