目录
抽象工厂模式【Abstract Factory Pattern】实现原理?适用场景及特点?优缺点?抽象工厂模式实现?
抽象工厂模式实现原理
抽象工厂模式相对于工厂方法模式来说,就是工厂方法模式是针对一个产品系列的,而抽象工厂模式是针对多个产品系列的,即工厂方法模式是一个产品系列一个工厂类,而抽象工厂模式是多个产品系列一个工厂类。在抽象工厂模式中,客户端不再负责对象的创建,而是把这个责任丢给了具体的工厂类,客户端只负责对对象的调用,从而明确了各个类的职责。并且当一系列相互关联的产品被设计到一个工厂类里后,客户端的调用将会变得非常简单,而且,如果要更换这一系列的产品,则只需要更换一个工厂类即可。
如果客户端需要创建一些产品结构,而这些产品结构又分别属于不同的产品类别,则可以使用抽象工厂模式,抽象工厂模式中抽象工厂类负责定义创建对象的接口,具体这一系列对象的创建工作由实现抽象工厂的具体工厂类来完成。
抽象工厂功能
抽象工厂模式的一个主要功能是它能够隔离要生成的具体产品类, 由于这些类的实际类名部被隐藏在工厂内部,因此客户端根本不需要关心如何对它们进行实例化的细节。每种设计模式都是针对特定问题的解决方案,而抽象工厂模式面临的问题则是当涉及到有多个产品等级结构,如何更好地进行软件体系结构的设计。
抽象工厂适用场景及特点
(1)多个相关的产品系列
当系统需要一次性创建一整套相关的产品时,抽象工厂模式非常有用。例如,一个图形用户界面工具包可能需要创建按钮、文本框、下拉框等各种控件,这些控件之间存在关联,可以通过抽象工厂模式统一创建。
(2)不同的产品等级结构
如果系统中存在不同的产品等级结构,而客户端需要使用一套产品族,抽象工厂模式可以提供一个统一的接口来创建不同等级结构的产品。
(3)产品变化频率低
抽象工厂模式对于产品族的变化和扩展非常友好,但对于单个产品的变化不太友好。如果产品的变化频率较低,抽象工厂模式是一个很好的选择。
(4)隐藏具体产品的实现
客户端只需要知道抽象产品的接口,而不需要关心具体产品的实现细节。这样可以降低客户端和具体产品类之间的耦合度。
(5)易于替换产品系列
由于抽象工厂模式将产品的创建封装在工厂类中,因此可以轻松替换整个产品系列,而不需要修改客户端代码。
总的来说,抽象工厂模式适合于需要创建一系列相关或相互依赖的对象,并且希望将产品的创建和使用解耦的场景。通过抽象工厂模式,可以实现产品族的扩展和替换,同时保持客户端代码的稳定性和灵活性。
抽象工厂模式的优缺点
优点
(1)产品族一致性
抽象工厂模式可以确保一次性创建一整套相关的产品,保证了这些产品之间的一致性,例如风格、主题等。
(2)易于替换产品系列
由于抽象工厂模式将产品的创建封装在工厂类中,因此可以轻松替换整个产品系列,而不需要修改客户端代码。
(3)隐藏具体产品的实现
客户端只需要知道抽象产品的接口,而不需要关心具体产品的实现细节。这样可以降低客户端和具体产品类之间的耦合度。
(4)符合开闭原则
抽象工厂模式可以轻松地添加新的产品族,而不需要修改现有的代码,符合开闭原则。
(5)提供一致的接口
抽象工厂模式提供了一致的接口来创建产品,这样可以让客户端代码更加简洁和易于维护。
缺点
(1)不易扩展产品等级结构
如果需要添加新的产品等级结构,比如增加新的按钮类型,需要修改抽象工厂接口和所有的具体工厂类,这可能会影响现有的代码。
(2)产品变化频率高
如果产品的变化频率较高,抽象工厂模式可能会导致系统变得复杂,因为每次添加新产品都需要修改抽象工厂接口和所有的具体工厂类。
(3)增加了系统的抽象性和理解难度
抽象工厂模式引入了额外的抽象层次,可能会增加系统的复杂性和理解难度。
总的来说,抽象工厂模式适合于需要创建一系列相关或相互依赖的对象,并且希望将产品的创建和使用解耦的场景。但是在产品等级结构经常变化的情况下,抽象工厂模式可能不是最佳选择。
抽象工厂模式实现
1、人类的接口定义
package com.uhhe.common.design.abstractfactory;
/**
* 定义一个人类的统称
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 13:48
*/
public interface Human {
/**
* 人是愉快的,会笑的,本来是想用smile表示,想了一下laugh更合适,好长时间没有大笑了;
*/
void laugh();
/**
* 人类还会哭,代表痛苦
*/
void cry();
/**
* 人类会说话
*/
void talk();
/**
* 定义性别
*/
void sex();
}
2、根据接口创建三个抽象类,也就是三个产品等级,实现 laugh()、cry()、talk() 三个方法
黑色人种
package com.uhhe.common.design.abstractfactory;
/**
* 黑色人种
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 13:53
*/
public abstract class AbstractBlackHuman implements Human {
@Override
public void laugh() {
System.out.println("黑人会哭");
}
@Override
public void cry() {
System.out.println("黑人会笑");
}
@Override
public void talk() {
System.out.println("黑人可以说话,一般人听不懂");
}
}
白色人种
package com.uhhe.common.design.abstractfactory;
/**
* 白色人种
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 13:53
*/
public abstract class AbstractWhiteHuman implements Human {
@Override
public void cry() {
System.out.println("白色人种会哭");
}
@Override
public void laugh() {
System.out.println("白色人种会大笑,侵略的笑声");
}
@Override
public void talk() {
System.out.println("白色人种会说话,一般都是但是单字节!");
}
}
黄色人种
package com.uhhe.common.design.abstractfactory;
/**
* 黄色人种
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 13:52
*/
public abstract class AbstractYellowHuman implements Human {
@Override
public void cry() {
System.out.println("黄色人种会哭");
}
@Override
public void laugh() {
System.out.println("黄色人种会大笑,幸福呀!");
}
@Override
public void talk() {
System.out.println("黄色人种会说话,一般说的都是双字节");
}
}
3、实现类(性别 + 肤色组合)
package com.uhhe.common.design.abstractfactory;
/**
* 女性黑种人
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 13:56
*/
public class BlackFemaleHuman extends AbstractBlackHuman {
@Override
public void sex() {
System.out.println("该黑种人的性别为女...");
}
}
package com.uhhe.common.design.abstractfactory;
/**
* 男性黑种人
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 13:56
*/
public class BlackMaleHuman extends AbstractBlackHuman{
@Override
public void sex() {
System.out.println("该黑种人的性别为男...");
}
}
package com.uhhe.common.design.abstractfactory;
/**
* 女性白种人
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 13:56
*/
public class WhiteFemaleHuman extends AbstractWhiteHuman {
@Override
public void sex() {
System.out.println("该白种人的性别为女...");
}
}
package com.uhhe.common.design.abstractfactory;
/**
* 男性白种人
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 13:56
*/
public class WhiteMaleHuman extends AbstractWhiteHuman{
@Override
public void sex() {
System.out.println("该白种人的性别为男...");
}
}
package com.uhhe.common.design.abstractfactory;
/**
* 女性黄种人
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 13:56
*/
public class YellowFemaleHuman extends AbstractYellowHuman {
@Override
public void sex() {
System.out.println("该黄种人的性别为女...");
}
}
package com.uhhe.common.design.abstractfactory;
/**
* 男性黄种人
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 13:56
*/
public class YellowMaleHuman extends AbstractYellowHuman{
@Override
public void sex() {
System.out.println("该黄种人的性别为男...");
}
}
4、定义枚举类型(用于指定实现类)
package com.uhhe.common.design.abstractfactory;
/**
* 世界上有哪些类型的人,列出来
* java enum类型尽量简单使用,尽量不要使用多态、继承等方法。毕竟用class完全可以代替enum
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 14:30
*/
public enum HumanEnum {
/**
* 女性人种
*/
YELLOW_FEMALE_HUMAN("com.uhhe.common.design.abstractFactory.YellowFemaleHuman"),
BLACK_FEMALE_HUMAN("com.uhhe.common.design.abstractFactory.BlackFemaleHuman"),
WHITE_FEMALE_HUMAN("com.uhhe.common.design.abstractFactory.WhiteFemaleHuman"),
/**
* 男性人种
*/
YELLOW_MALE_HUMAN("com.uhhe.common.design.abstractFactory.YellowMaleHuman"),
BLACK_MALE_HUMAN("com.uhhe.common.design.abstractFactory.BlackMaleHuman"),
WHITE_MALE_HUMAN("com.uhhe.common.design.abstractFactory.WhiteMaleHuman");
private String value = "";
/**
* 定义构造函数,目的是Data(value)类型的相匹配
*
* @param value 名称
*/
private HumanEnum(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
}
5、工厂类
工厂接口
package com.uhhe.common.design.abstractfactory;
/**
* 接口工厂方法
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 14:01
*/
public interface HumanFactory {
/**
* 制造黄色人种
*
* @return Human
*/
Human createYellowHuman();
/**
* 制造一个白色人种
*
* @return human
*/
Human createWhiteHuman();
/**
* 制造一个黑色人种
*
* @return Human
*/
Human createBlackHuman();
}
抽象工厂
package com.uhhe.common.design.abstractfactory;
/**
* 编写一个抽象类,根据enum创建一个人类出来
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 14:34
*/
public abstract class AbstractHumanFactory implements HumanFactory {
/**
* 给定一个性别人种,创建一个人类出来 专业术语是产生产品等级
*
* @param humanEnum 人类枚举
* @return Human
*/
protected Human createHuman(HumanEnum humanEnum) {
Human human = null;
// 如果传递进来不是一个Enum中具体的一个Element的话,则不处理
if (!humanEnum.getValue().equals("")) {
try {
//直接产生一个实例
human = (Human) Class.forName(humanEnum.getValue()).newInstance();
} catch (Exception e) {
// 因为使用了enum,这个种异常情况不会产生了,除非enum有问题;
e.printStackTrace();
}
}
return human;
}
}
女性创建工厂
package com.uhhe.common.design.abstractfactory;
/**
* 女性创建工厂
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 14:40
*/
public class FemaleHumanFactory extends AbstractHumanFactory {
/**
* 创建一个女性黑种人
*
* @return Human
*/
@Override
public Human createBlackHuman() {
return super.createHuman(HumanEnum.BLACK_FEMALE_HUMAN);
}
/**
* 创建一个女性白种人
*
* @return Human
*/
@Override
public Human createWhiteHuman() {
return super.createHuman(HumanEnum.WHITE_FEMALE_HUMAN);
}
/**
* 创建一个女性黄种人
*
* @return Human
*/
@Override
public Human createYellowHuman() {
return super.createHuman(HumanEnum.YELLOW_FEMALE_HUMAN);
}
}
男性创建工厂
package com.uhhe.common.design.abstractfactory;
/**
* 男性创建工厂
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 14:36
*/
public class MaleHumanFactory extends AbstractHumanFactory {
/**
* 创建一个男性黑种人
*
* @return Human
*/
@Override
public Human createBlackHuman() {
return super.createHuman(HumanEnum.BLACK_MALE_HUMAN);
}
/**
* 创建一个男性白种人
*
* @return Human
*/
@Override
public Human createWhiteHuman() {
return super.createHuman(HumanEnum.WHITE_MALE_HUMAN);
}
/**
* 创建一个男性黄种人
*
* @return Human
*/
@Override
public Human createYellowHuman() {
return super.createHuman(HumanEnum.YELLOW_MALE_HUMAN);
}
}
6、抽象工厂使用
package com.uhhe.common.design.abstractfactory;
/**
* @author nizhihao
* @version 1.0.0
* @date 2023/2/27 14:39
*/
public class NvWa {
/**
* 抽象工厂模式【Abstract Factory Pattern】
* <p>
* 两个八卦炉,一个造女的,一个造男的,开足马力,一直造到这个世界到现在这个模式为止。
* <p>
* 工厂模式有哪些优缺点?
* 先说优点,非常重要的有点就是,工厂模式符合 OCP 原则(开闭原则,扩展开发,修改封闭),怎么说呢,比如就性别的问题,
* <p>
* 这个世界上还存在双性人,是男也是女的人,那这个就是要在我们的产品族中增加一类产品,
* 同时再增加一个工厂就可以解决这个问题,不需要再来实现了吧,很简单画下类图,然后实现下。
* <p>
* 那还有没有其他好处呢?
* 抽象工厂模式,还有一个非常大的有点,高内聚,低耦合,在一个较大的项目组,
* 产品是由一批人定义开发的,但是提供其他成员访问的时候,只有工厂方法和产品的接口,
* 也就是说只需要提供 Product Interface 和 Concrete Factory 就可以产生自己需要的对象和方法,
* Java 的高内聚低耦合的特性表现的一览无遗
*/
public static void main(String[] args) {
// 第一条生产线,男性生产线
HumanFactory maleHumanFactory = new MaleHumanFactory();
// 第二条生产线,女性生产线
HumanFactory femaleHumanFactory = new FemaleHumanFactory();
// 生产线建立完毕,开始生产人了:
Human maleYellowHuman = maleHumanFactory.createYellowHuman();
Human femaleYellowHuman = femaleHumanFactory.createYellowHuman();
maleYellowHuman.talk();
maleYellowHuman.cry();
maleYellowHuman.laugh();
maleYellowHuman.sex();
System.out.println("\n");
femaleYellowHuman.talk();
femaleYellowHuman.cry();
femaleYellowHuman.laugh();
femaleYellowHuman.sex();
/*
* .....
*/
}
}