深入浅出设计模式——从球赛中悟抽象工厂模式

一、概念

    抽象工厂模式,从名字上看就和工厂模式关系密切。所谓抽象工厂,就是把工厂模式中的工厂再进行抽象化,以满足创建一个产品族的多个产品。

    放在足球环境下,抽象工厂就好比是青训营,而继承抽象工厂的具体工厂就是各个不同的青训营,例如拉玛西亚青训营和阿贾克斯青训营。不同的工厂产出的产品有各自的特色,就好比拉玛西亚青训营培养出来的球员普遍技术非常细腻,而阿贾克斯青训营培养出来的球员各个都能体现出极强的适应能力,但是他们又都是球员,所以各青训营培养出来的球员属于同一产品族中的不同的产品(有点儿绕,不知道大家是否能理解)。客户端就是各足球队,球队可以根据自己的需要到不同的青训营中去挑选球员。这里,足球队只需要确定自己需要哪个青训营中哪个位置的球员就好,其他的事情完全不用关心。

二、使用场景

    在需要构造一组产品,并且这组产品都具有相同约束的时候;客户端不关心如何创建它所需要的类的时候。

三、结构

    抽象工厂模式结构比工厂模式就要复杂一些了:

    抽象产品(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);
    }
    
}

    工厂类重写产品的创建方法,返回该工厂对应的产品,这里因为我将所有的产品都实现lePlayer接口,所以可以用一个公共的创建方法创建,如果产品没有实现同一个接口该如何处理留给大家自己摸索。

    我们来测试一下各大青训营是否可以正常工作:

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

------------------------------------------------------------------------

欢迎关注我的个人公众号,推送最新文章

转载于:https://my.oschina.net/jack90john/blog/1817057

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值