实例探索Java模式之路——抽象工厂模式

本文介绍抽象工厂模式的概念、结构及应用场景,通过一个具体例子详细解释如何实现该模式,帮助读者理解并掌握抽象工厂模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

抽象工厂模式


1、抽象工厂模式是对象的创建模式。抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。


2、抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,创建多个产品对象。

这就是抽象工厂模式的用意。

工厂类负责创建抽象产品的具体子类的实例。



3、什么是产品簇:是指位于不同产品等级结构中,功能相关联的产品组成的家族。每一产品簇含有的产品数目,与产品等级结构的数目是相等的。
产品的等级结构和产品簇将产品按照不同方向划分,形成一个二维的坐标系。


图中四个产品簇,分布在三个不同的产品等级结构中。这个坐标图叫相图。

比如水果和蔬菜都是产品,是属于不同的产品等级结构,而北方的蔬菜和北方的水果都是属于北方产品的集合,是属于同一个产品簇,热带水果和热带蔬菜也是属于同一产品簇。


在抽象工厂的相图中,对应每一个产品簇都有一个具体的工厂。每一个具体工厂负责创建属于同一个产品簇,但是分属于不同的等级结构的产品。


4、假如一个子系统需要一些产品对象,而这些产品对象又属于一个以上的产品等级结构。为了将消费这些产品对象的责任和创建这些对象的责任分开,
可以引入抽象工厂模式,这样消费产品的一方不需要直接参与产品的创建工作,只需要向一个公用的工厂接口请求所需要的产品。


5、抽象工厂模式结构
通过抽象工厂模式,可以处理具有相图或相似等级结构的多个产品簇中的产品对象的创建问题。


抽象工厂角色:这个角色是工厂方法模式的核心,他是与应用程序无关的。任何在模式中创建对象的工厂必须实现这个接口。
具体工厂角色:这个角色是实现了抽象工厂接口的具体Java类。具体工厂角色含有与应用程序密切相关的逻辑,并且受到应用程序的调用以创建产品对象。
抽象产品角色:工厂方法模式所创建对象的超类型,也是产品对象的共同父类或共同拥有的接口。
具体产品角色:这个角色实现了抽象产品角色所声明的接口。工厂方法模式所创建的每一个对象都是某个具体产品角色的实例。


6、抽象工厂模式相图


抽象工厂模式中,有多个产品等级结构,多个具体工厂,每个具体工厂分别对相应的产品簇负责。


7、抽象工厂模式使用场景;
1、一个系统不应当依赖于产品类实例如何被创建、组合和表达细节,这对于所有形态的工厂模式都是重要的。
2、系统的产品有多于一个的产品簇,而系统只消费某一簇;
3、同属于同一个产品簇的产品在一起使用,
4、所有产品以同样的接口出现,客户端不依赖于实现。


8、抽象工厂模式功能增强对开-闭原则的支持

对于一个涉及多个产品等级结构和多个产品簇的系统,功能增强有两个方面


1、增加新的产品簇
在产品等级结构的数目不变的情况下,增加新的产品簇,意味着每一个产品等级结构中增加一个或多个新的具体或者抽象的产品角色。
当产品等级调整时,需要将工厂等级做响应的调整,产品等级结构出现新的元素,需要向工厂等级结构中加入相应的新的元素。

设计师只需要向系统加入新的工厂类就可以了,不必修改已有的工厂角色或者产品角色,在新增产品簇时,抽象工厂模式支持开——闭原则。


2、增加新的产品等级结构
在产品簇数目不变的情况下,所有的产品等级结构中的产品数目不变,但多出来一个与现在产品等级结果平行的新的产品等级结构。
要做到这点,就需要修改所有的工厂角色,给每个工厂类新增一个新的工厂方法。对于产品等级结构的增加,抽象工厂模式不支持开-闭原则。


9、通过一个抽象工厂模式例子深入理解;


抽象工厂角色
提供的是(两个)不同等级结构的产品对象。


import IProduct.Fruit;
import IProduct.Veggie;


public interface Gardener {
/**
* 水果的工厂方法
*/
public Fruit creatFruit(String name);


/**
* 蔬菜的工厂方法
*/
public Veggie creatVeggie(String name);
}


具体工厂,实现了抽象工厂角色要求的两个工厂方法,分别提供两个产品等级结构中某一个产品对象。
有多少个产品等级结构,就会在工厂角色发现多少个工厂方法。每一个产品等级结构有多少具体产品,就有多少个产品簇,也就会在工厂等级结构发现多少个具体工厂。
一个产品簇对应一个产品工厂。
北方水果,和北方蔬菜属于同一个产品簇,热带水果和热带蔬菜也是同一个产品簇,每一个产品簇对应一个具体工厂。


import IFactory.Gardener;
import IProduct.Fruit;
import IProduct.Veggie;
import IProduct.productimpl.NorthernFruit;
import IProduct.productimpl.NorthernVeggie;


public class NorthernGardener implements Gardener {
/**
* 北方水果的工厂方法
*/
@Override
public Fruit creatFruit(String name) {
return new NorthernFruit(name);
}


/**
* 北方蔬菜的工厂方法
*/
@Override
public Veggie creatVeggie(String name) {
return new NorthernVeggie(name);
}
}


import IFactory.Gardener;
import IProduct.Fruit;
import IProduct.Veggie;
import IProduct.productimpl.TropicalFruit;
import IProduct.productimpl.TropicalVeggie;


public class TropicalGardener implements Gardener {
/**
* 热带水果的工厂方法
*/
@Override
public Fruit creatFruit(String name) {
return new TropicalFruit(name);
}


/**
* 热带蔬菜的工厂方法
*/
@Override
public Veggie creatVeggie(String name) {
return new TropicalVeggie(name);
}
}


抽象产品角色,水果、蔬菜就是两个不同的等级结构


package IProduct;


public interface Fruit {
// 生长
void grow();


// 收获
void harvest();


// 种植
void plant();
}


package IProduct;


public interface Veggie {
}


具体产品角色
package IProduct.productimpl;


import IProduct.Fruit;


public class NorthernFruit implements Fruit {


private String name;


public NorthernFruit(String name) {
System.out.println("北方水果" + name);
}


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


@Override
public void grow() {
// TODO Auto-generated method stub

}


@Override
public void harvest() {
// TODO Auto-generated method stub

}


@Override
public void plant() {
// TODO Auto-generated method stub

}
}


package IProduct.productimpl;


import IProduct.Veggie;


public class NorthernVeggie implements Veggie {


private String name;


public NorthernVeggie(String name) {
System.out.println("北方蔬菜" + name);
}


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


}


import IProduct.Fruit;


public class TropicalFruit implements Fruit {


private String name;


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


public TropicalFruit(String name) {
System.out.println("热带水果"+name);
}


@Override
public void grow() {
// TODO Auto-generated method stub

}


@Override
public void harvest() {
// TODO Auto-generated method stub

}


@Override
public void plant() {
// TODO Auto-generated method stub

}


}


import IProduct.Veggie;


public class TropicalVeggie implements Veggie {


private String name;


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


public TropicalVeggie(String name) {
System.out.println("热带蔬菜"+name);
}


}


客户端角色
package client;


import IFactory.factoryimpl.NorthernGardener;
import IFactory.factoryimpl.TropicalGardener;


public class client {


public static void main(String[] args) {


NorthernGardener northerngardener = new NorthernGardener();
northerngardener.creatFruit("葡萄");
northerngardener.creatVeggie("青瓜");


TropicalGardener tropicalgardener = new TropicalGardener();
tropicalgardener.creatFruit("香蕉");
tropicalgardener.creatVeggie("莴笋");
}
}


本例中有两个产品等级结构,而每个产品等级结构又有两个产品,也就是两个产品簇。

因此,工厂等级结构就会出现两个具体工厂对应两个产品簇;每个工厂类又有两个工厂方法对应两个产品等级结构。

在真实的系统,产品等级结构的数目与每个产品等级结构中的产品的数目也就是产品簇的数目一般不相等。


通过此实例,相信对该模式有了进一步的认识。

每天努力一点,每天都在进步。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

powerfuler

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值