一、概念
抽象工厂模式,从名字上看就和工厂模式关系密切。所谓抽象工厂,就是把工厂模式中的工厂再进行抽象化,以满足创建一个产品族的多个产品。
放在足球环境下,抽象工厂就好比是青训营,而继承抽象工厂的具体工厂就是各个不同的青训营,例如拉玛西亚青训营和阿贾克斯青训营。不同的工厂产出的产品有各自的特色,就好比拉玛西亚青训营培养出来的球员普遍技术非常细腻,而阿贾克斯青训营培养出来的球员各个都能体现出极强的适应能力,但是他们又都是球员,所以各青训营培养出来的球员属于同一产品族中的不同的产品(有点儿绕,不知道大家是否能理解)。客户端就是各足球队,球队可以根据自己的需要到不同的青训营中去挑选球员。这里,足球队只需要确定自己需要哪个青训营中哪个位置的球员就好,其他的事情完全不用关心。
二、使用场景
在需要构造一组产品,并且这组产品都具有相同约束的时候;客户端不关心如何创建它所需要的类的时候。
三、结构
抽象工厂模式结构比工厂模式就要复杂一些了:
抽象产品(AbstractStriker,AbstractGoalkeeper,AbstractDefender):这里有三个场上位置就是三个抽象产品,由于都是球员,所以我都实现了Player接口,这一步不是必要的,我只是为了后面方便。
产品类:继承产品族的实现类,对应各自的工厂。
抽象工厂(School):具体的工厂通过实现抽闲工厂来生产不同产品族中的对应的产品。
工厂类:实现抽象工厂的工厂类,客户端通过它来创建一族产品。
四、实现
首先创建一个抽象产品:
public abstract class AbstractGoalkeeper implements Player {
@Override
public String getPosition() {
return "门将";
}
@Override
public Integer getScore() {
Random random = new Random();
return 40 + random.nextInt(60);
}
}
这个产品中有两个共有的方法实现,然后我们创建一个产品类:
public class LaMasiaGoalkeeper extends AbstractGoalkeeper {
@Override
public String getSkill() {
return "反应敏捷,脚下技术出众";
}
}
产品类中包含了每个青训营培养出来的球员的特色(其他的抽象产品和产品类跟这个都大致一样,大家可以从源码中下载,我就不一一列举了)。接下来我们定义一个抽象工厂:
public interface School {
Player createGoalkeeper();
Player createDefender();
Player createStriker();
}
抽象工厂中包含了各个产品族的创建方法,最后我们来看看工厂类:
public class LaMasia extends AbstractSchool {
@Override
public Player createGoalkeeper() {
return createPlayer(LaMasiaGoalkeeper.class);
}
@Override
public Player createDefender() {
return createPlayer(LaMasiaDefender.class);
}
@Override
public Player createStriker() {
return createPlayer(LaMasiaStriker.class);
}
}
工厂类重写产品的创建方法,返回该工厂对应的产品,这里因为我将所有的产品族都实现类Play而接口,所以可以用一个公共的创建方法创建,如果产品族没有实现同一个接口该如何处理留给大家自己摸索。
我们来测试一下各大青训营是否可以正常工作:
public class Team {
public static void main(String[] args) {
School school1 = new Ajax();
Player goalkeeper1 = school1.createGoalkeeper();
System.out.println("阿贾克斯青训营培养的门将信息:{ 位置:" +
goalkeeper1.getPosition() + "; 特长: " + goalkeeper1.getSkill() +
"; 综合评分: " + goalkeeper1.getScore() + "}");
School school2 = new LaMasia();
Player goalkeeper2 = school2.createGoalkeeper();
System.out.println("门将信息:{ 位置:" +
goalkeeper2.getPosition() + "; 特长: " + goalkeeper2.getSkill() +
"; 综合评分: " + goalkeeper2.getScore() + "}");
}
}
运行结果:
可以看出,球队(客户端)可以从两大青训营(工厂)中获取相对应的不同特长的球员(产品)。
五、优势
1、具体类的创建实例过程与客户端分离,客户端不用关系对象是如何被创建的。
2、符合开闭原则。
3、抽象工厂模式可以保证同一个工厂里生产出来的产品是同一族产品。
六、局限性
产品族的扩展相对麻烦。当然了,世界上没有十全十美的模式,每个设计模式都有它适用的地方,只要我们的使用方式得当,那么抽象工厂模式可以帮助我们写出漂亮优雅的代码。
附源码地址:https://gitee.com/jack90john/factory
------------------------------------------------------------------------
欢迎关注我的个人公众号,推送最新文章