java思想和我们生活息息相关。工厂模式也可以在生活中找到大量的例子。

大多数人都玩过网游,就拿当前比较火的剑灵来说,进入剑灵游戏第一步就是创建角色,有剑士、刺客、力士、灵剑等角色。如果你是游戏开发者,你会如何设计一个框架来给用户选择角色呢?

首先,我们应该有个接口,用来定义角色类型。

接口:

public interface CustomRole{}

其次应该有一个角色库,用来给用户提供角色选择,比如用户输入了角色类型、名称、种族、阵营、性别等等参数后,我们就应该从角色库匹配一个对应的角色提供给用户。

角色库的类:

public class RoleFactory{}

角色库中包含创建角色的方法 :

/**
     * 创建角色
     * @param roleType 角色类型
     * @param uName 角色名称
     * @param uSex 角色性别
     * @param uCamp 角色阵营
     * @return
     */
    public CustomRole createRole(String roleType, String uName, String uSex, String uCamp ){
        if(roleType.equals("JianShi")){
            return new JianShi(uName, uSex, uCamp);
        }else if(roleType.equals("CiKe")){
            return new CiKe(uName, uSex, uCamp);
        }
        return null;
    }

我们继续定义角色,有那么多的角色,角色不同种类有相同的属性,我们先定义一个基类实现CustomRole接口:

/**
 * 角色的基类用于扩展角色。
 *
 */
public abstract class BaseRole implements CustomRole {

    protected String roleType;
    protected String uName;
    protected String uSex; 
    protected String uCamp;
}

通过基类,我们扩展具体的“剑士”这个类:

/**
 *剑士  
 *
 */
public class JianShi extends BaseRole{

    public JianShi(String name, String sex , String camp) {
        this.uName = name;
        this.uSex = sex;
        this.uCamp = camp;
    }
}

现在我们就可以用角色工厂创建一个角色了:

private void testFactory() {
        RoleFactory roleFactory = new RoleFactory();
        JianShi mJianShi = (JianShi) roleFactory.createRole("JianShi", "一只小剑客", "", "天辉军团");
    }

 

 

以上是第一种方法,继续说第二种方法,等说完在比较。

第二种方法和第一种方法稍有不同,保持角色基类和其子类不变,我们把工厂本身也具体化一下:有剑士工厂,有刺客工厂等等:

首先,我们定义一个工厂接口:

public interface CustomFactory {

    public CustomRole createCustomRole(String uName, String uSex, String uCamp);
}

里面有个接口方法:创建角色,注意和第一种方法中工厂里的创建角色方法是不是有一丢丢不同?那就是不用传角色类型了!

接着,我们创建具体的“剑士”这个角色的工厂:

public class JianShiFactory implements CustomFactory {

    @Override
    public CustomRole createCustomRole(String uName, String uSex, String uCamp) {
        return new JianShi(uName, uSex, uCamp);
    }

}

就是实现了CustomFactory 接口和其中的创建角色方法,返回了一个具体的剑士角色。

测试:

private void testFactort2() {
        CustomFactory jainshiFactory = new JianShiFactory();
        JianShi mJianShi = (JianShi) jainshiFactory.createCustomRole("一只小剑客", "", "天辉军团");
    }

private void testFactory() {
        RoleFactory roleFactory = new RoleFactory();
        JianShi mJianShi = (JianShi) roleFactory.createRole("JianShi", "一只小剑客", "", "天辉军团");
    }

并且附上第一种方式的测试,对比。

通过对比我们可以发现,第二种方式比第一种方式多了一个接口,少了一个传入参数。

总结:方案一在实例化时必须要知道你要得到的是什么角色(角色类型),才能创建对应角色;第二种则不需要,通过工厂名称就可以知道要创建的是什么角色了。

个人觉得第一种适合子类种类不多的情况,不然需要写很多if()else去过滤类型。第二种适合子类型较多的情况,但是代码量要多点。