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

一、概念

    工厂模式是非常常用的一种设计模式,它主要是用来创建对象。通过工厂模式创建对象与通过new创建对象所不同的是,工厂模式不会向客户端暴露创建逻辑,而是通过一个接口来指向新创建的对象。

    放在足球环境下,工厂就好比是青训营,客户端就是各足球队,青训营培养出来的球员交给足球队使用。这里,足球队并不需要知道青训营是如何把一个不会踢球的小孩培养成一个球员的,只需要告诉青训营我需要一个门将或者其他位置的球员,青训营就会对应的把一个符合标准的球员培养出来。

二、使用场景

    在不同的条件下需要创建不同的对象时,我们可以使用工厂模式。同时我们需要注意简单的,只需要通过new就可以创建的对象就不要用工厂模式了,工厂模式适合用来创建较复杂的对象。因为使用工厂模式,需要引入一个工厂类,会增加系统的复杂度。

三、结构

    可以看出工厂模式结构并不复杂:

    产品接口(Player):被创建的对象都需要实现的接口,定义了工厂创建出的对象类型。

    工厂类(School):用来创建对象,客户端只需要通过这个类来创建对象,而不需要直接访问具体对象。

四、实现

    首先创建一个接口用来定义产品:

public interface Player {
    String getPosition();  //球员位置
    String getSkill();     //球员特长
    Integer getScore();    //球员能力评分
}

    可以看到球员共有的几个方法,获取球员位置信息,获取球员特长,获取球员综合评分。然后我们简单的创建几个球员的实现类:

public class Goalkeeper implements Player {

    @Override
    public String getPosition() {
        return "门将";
    }

    @Override
    public String getSkill() {
        return "反应敏捷,脚下技术出众";
    }

    @Override
    public Integer getScore() {
        Random random = new Random();
        return 40 + random.nextInt(60);
    }

}

    这里我就只列举一个例子来,其他的大家可以自行添加,或者到文末附到源码路径中下载,不同的球员我们给出了不同的实现方法。接下来我们需要一个工厂了:

class School {

    static <T extends Player> Player createPlayer(Class<T> position) {
        Player player = null;
        try {
            player = position.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return player;
    }

}

    其实这个工厂类是我偷懒随意写的,如果构造方法不是默认方法的情况下工厂类该如何处理还请大家自行思考。可以提示一下,可以通过反射获取指定构造方法返回,然后在通过构造方法穿件对象就OK了。

    好了,现在我们来就来创建一个客户来测试一下这个青训营是否可以正常工作:

public class Team {

    public static void main(String[] args) {
        Player player1 = School.createPlayer(Goalkeeper.class);
        System.out.println("1号球员信息:{ 位置:" +
                player1.getPosition() + "; 特长: " + player1.getSkill() +
                "; 综合评分: " + player1.getScore() + "}");

        Player player2 = School.createPlayer(Defender.class);
        System.out.println("2号球员信息:{ 位置:" +
                player2.getPosition() + "; 特长: " + player2.getSkill() +
                "; 综合评分: " + player2.getScore() + "}");

        Player player3 = School.createPlayer(Striker.class);
        System.out.println("3号球员信息:{ 位置:" +
                player3.getPosition() + "; 特长: " + player3.getSkill() +
                "; 综合评分: " + player3.getScore() + "}");
    }
}

     查看执行结果:

    可以看出,客户端并没有访问任何球员类,而是通过School的一个创建方法来创建对象的。

五、优势

    1、多数情况下调用者只需要知道对象的名字就可以通过工厂模式来创建;

    2、如果想增加一个产品只需要再增加一个产品接口实现即可,有非常好的可扩展性;

    3、调用者只关心产品的接口而需要考虑产品的具体实现。

六、局限性

    一定程度上增加了系统的复杂度,因为每增加一个产品就需要增加一个实现类,如果是其他产品那么还需要新增对应的工厂类。当然了,世界上没有十全十美的模式,每个设计模式都有它适用的地方,只要我们的使用方式得当,那么工厂模式可以帮助我们写出漂亮优雅的代码。

附源码地址:https://gitee.com/jack90john/factory

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

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

猜你喜欢

转载自my.oschina.net/jack90john/blog/1816150