现在假设有多个结构相同的产品层次类
问题:我们是否仍然使用工厂方法模式?
一些想法
对于每个产品层次类,我们构造一个工厂层次类
下图中使用的三个创建者
注释:这不是很好,因为有太多的Creator类 —— 还有其他更好的解决方法吗?
新的解决方案——请注意以下产品结构相同
二、抽象工厂模式理论 01 抽象工厂模式类图 02 抽象工厂模式介绍- 抽象工厂模式简介
- 抽象工厂模式采用与工厂方法模式相同的概念
抽象工厂创建者是一个类,它提供了一个接口来生成一组对象
在Java编程语言中,它可以实现为一个界面和一个抽象类
- 抽象工厂模式采用与工厂方法模式相同的概念
- 抽象工厂模式的组件
- 一族(相关的)层次类
工厂接口,带有几个实现子类(子类个数与每个产品层次类的个数相同)
每个工厂子类都负责创建所有的Product层次类的指定的子类对象
- 一族(相关的)层次类
- 何时使用抽象工厂模式?
- 当客户对象想要创建一族层次类的某个子类对象,而不想知道到底是哪个子类对象被创建了。
- 当客户端对象想要创建一组相关的、依赖的类的一个实例,而不需要知道要实例化哪个具体的类时,使用抽象工厂模式。
- 如果不使用抽象工厂模式,将会发生什么?
- 如果我们不使用抽象工厂,那么在创建此类实例时,选择适当类所需的实现需要出现在所有地方。
需要使用大量的条件语句。
- 如果我们不使用抽象工厂,那么在创建此类实例时,选择适当类所需的实现需要出现在所有地方。
- Client对象怎样使用抽象工厂模式?
- 回答:使用具体的工厂子类创建Product子类对象,而不必知道到底哪个子类对象被创建类。
- Client对象利用这些具体的工厂来创建对象,因此,不需要知道实际实例化的是哪个具体类。
1、产品不同
(1)对于工厂方法模式,产品是一个单一产品类层次结构
(2)对于抽象工厂模式,产品是一组产品类层次结构
2、有关可扩展性
(1)工厂方法模式遵循开闭原则,同时
(2)抽象工厂模式只部分遵循开闭原则
2.5、关于开闭原则——两种情况
-
Case1
- 如果你添加一个ProductA3和ProductB3,也是创造者类层次结构需要添加类CreatorC。在此情况下,抽象工厂模式满足开闭原则
-
Case2
- 如果你添加了一个新产品 hierarchy ProductC,然后你需要在ConcreteCreator1,ConcreteCreator2添加一个新方法“+getObjC: ProductC”
- 这意味着您需要修改现有的工厂类层次结构,因此它不遵循开闭原则
- 层次结构:层次结构
让我们设计一个web应用程序来查询不同类型建筑的特征。
考虑两种类型的建筑:住宅和共管公寓。
此外,建筑可以是任何一种——Super or Medium
因为House和Condo代表了两种产品,每一种产品都可以分为super和medium,所以我们可以使用下面的抽象工厂模式
-
设计原因
- 如果我们不使用抽象工厂模式,而只是直接调用类House和Condo中的方法,
然后在ClientGUI中,我们需要编写大量的条件语句,这不利于扩展和维护
- 如果我们不使用抽象工厂模式,而只是直接调用类House和Condo中的方法,
-
设计好处
-
责任分离
选择和实例化适当的House/Condo实现者的责任可以从应用程序对象转移到单独的指定抽象工厂类。
-
关于建筑工厂类的层次结构
它只声明所需的接口,而将类选择和实例化的实际实现细节留给其实现者。
-
-
关于client对象AbstractFactoryGUI类:
它使用实现BuildingFactory接口的具体工厂实例来创建对象 表示不同类型和类别的房子,而不需要知道需要实例化的实际具体类。
Client对象不需要知道这些具体工厂类的存在。
-
AbstractFactoryGUI如何工作?
- 当搜索按钮被点击之后,一个建筑物类别和类型组合被选中,客户端AbstractFactoryGUI调用在抽象BuildingFactory类中的静态的getBuildingFactory(String type)方法
- getBuildingFactory(String type) 方法创建了一个适当的工厂对象并且返回它作为一个BuildingFactory类型的对象。
- 工厂对象在内部从它控制的建筑家族(SuperHouse/SuperCondo或MediumHouse/MediumCondo)中创建一个适当类的实例,并将其作为House/Condo类型的对象返回。
- Client类AbstractFactoryGUI甚至不知道House/Condo的存在
-
client AbstractFactoryGUI 不需要不同的具体的House/Condo类。
- 它只是调用House/Condo接口声明的方法,比如: getHouseInfo or getCondoInfo
public interface House {
public String getHouseInfo();
}
public class SuperHouse implements House {
public String getHouseInfo() {
return "superHouse.html";
}
}
public class MediumHouse implements House{
public String getHouseInfo() {
return "mediumHouse.html";
}
}
public interface Condo {
public String getCondoInfo();
}
public class SuperCondo implements Condo{
public String getCondoInfo(){
return "superCondo.html";
}
}
public class MediumCondo implements Condo{
public String getCondoInfo(){
return "mediumCondo.html";
}
}
public abstract class BuildingFactory{
public static final String SUPER = "Super Class";
public static final String MEDIUM = "Medium Class";
public abstract House getHouse();
public abstract Condo getCondo();
public static BuildingFactory getBuildingFactory(String type){
BuildingFactory bf = null;
if (type.equals(BuildingFactory.SUPER)){
bf = new SuperBuildingFactory();
}
else if (type.equals(BuildingFactory.MEDIUM)){
bf = new MediumBuildingFactory();
// 真奇怪,在超类中创建子类对象。你可曾遇到过?
}
return bf;
}
}
public class MediumBuildingFactory extends BuildingFactory {
public House getHouse(){
return new MediumHouse();
}
public Condo getCondo(){
return new MediumCondo();
}
}
public class SuperBuildingFactory extends BuildingFactory {
public House getHouse(){
return new SuperHouse();
}
public Condo getCondo(){
return new SuperCondo();
}
}
public class AbstractFactoryGUI extends JFrame {
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent ae) {
if (ae.getActionCommand().equals(AbstractFactoryGUI.SEARCH)) {
String clas = (String) cmbHouseClass.getSelectedItem();
String type = (String) cmbHouseType.getSelectedItem();
BuildingFactory bf = BuildingFactory.getBuildingFactory(clas);
if (type.equals(AbstractFactoryGUI.HOUSE)) {
House hs = bf.getHouse();
String fileNm = hs.getHouseInfo();
putHouseInfoToScreen(fileNm);
}
if (type.equals(AbstractFactoryGUI.CONDO)) {
Condo cd = bf.getCondo();
String fileNm = cd.getCondoInfo();
putHouseInfoToScreen(fileNm);
}
}
}}



