白话设计模式之工厂方法模式

在游戏中有很多房子、车子模型,玩的时候就想难道这些都是直接用new的方式创建出来的吗?不太可能,直接用new的话,开发游戏场景的时候工程师还需要关心房子创建的具体细节,比较影响工作效率,所以我更倾向于认为他们使用了工厂方法模式在管理模型的创建。

简单工厂模式

如果要创建白色房子和红色房子该怎么设计呢?并且要便于管理。

我最初的想法是:创建一个工厂类,然后根据调用方传入的参数判断是new个白房子还是new个红房子返回。

但是房子都是有共性的,比如它们都要有展示功能,所以可以作为约束放到抽象基类中。

UML类图如下:

publicabstractclassAbstractHouse{
    /**
     * 创建房子
     *
     * @param locationX 横向坐标
     * @param locationY 纵向坐标
     * @param angle:角度
     */publicabstractvoidshow(double locationX, double locationY, double angle);
}

publicclassRedHouseextendsAbstractHouse{
    @Overridepublicvoidshow(double locationX, double locationY, double angle){
        System.out.println("红色房子展示完成。展示效果:横向坐标:" + locationX + " 纵向坐标:" + locationY + " 角度:" + angle);
    }
}

publicclassWhiteHouseextendsAbstractHouse{
    @Overridepublicvoidshow(double locationX, double locationY, double angle){
        System.out.println("白色房子展示完成。展示效果:横向坐标:" + locationX + " 纵向坐标:" + locationY + " 角度:" + angle);
    }
}
publicclassHouseFactory{
    public AbstractHouse createHouse(String houseName){
        switch (houseName) {
            case"白房子": returnnew WhiteHouse();
            case"红房子": returnnew RedHouse();
            default: returnnull;
        }
    }
}
publicclassHouseClient {publicstaticvoidmain(String[] args){
        AbstractHouse whiteHouse = new HouseFactory().createHouse("白房子");
        whiteHouse.show(32, 60, 1);
        System.out.println("-------------------------------");
        AbstractHouse redHouse = new HouseFactory().createHouse("红房子");
        redHouse.show(122, 545, 35);
    }
}

运行打印出来的结果如下:

这样一个HouseFactory就可以管理所有房子模型的创建了,如果要新加一种房子,也只需要在HouseFactory中增加一种switch case就行了,如果你希望HouseFactory是全局共享的,还可以把createHouse改成静态方法。

但是这种结构不容易扩展,比如要求再增加对车辆的创建管理,该如何做呢?咱们的工厂方法模式就开始发挥作用了。

工厂方法模式

如果要对车子和房子统一进行管理,在coding之前,可以先捋下思路。

首先需要对模型做抽象:

白房子红房子需要一个共同的抽象父类

摩托车吉普车也需要一个共同的抽象父类(这里为了突出工厂分离的必要性,单独为车辆增加了一种“速度”的属性)

它们的抽象父类还可以做一层抽象,是所有模型的抽象父类。

然后对抽象工厂做设计:

房子的创建需要一个工厂

车辆的创建也需要一个工厂

它们之上可以加层抽象父类,是所有模型工厂的抽象父类。

UML类图如下:

/**
 * 抽象模型实体
 */publicabstractclassAbstractModel{
    publicabstractvoidshow(double locationX, double locationY, double angle);
}
/**
 * 抽象房子实体
 */publicabstractclassAbstractHouseextendsAbstractModel{

}

/**
 * 红房子实体
 */publicclassRedHouseextendsAbstractHouse{
    @Overridepublicvoidshow(double locationX, double locationY, double angle){
        System.out.println("红色房子展示完成。展示效果:横向坐标:" + locationX + " 纵向坐标:" + locationY + " 角度:" + angle);
    }
}

/**
 * 白房子实体
 */publicclassWhiteHouseextendsAbstractHouse{
    @Overridepublicvoidshow(double locationX, double locationY, double angle){
        System.out.println("白色房子展示完成。展示效果:横向坐标:" + locationX + " 纵向坐标:" + locationY + " 角度:" + angle);
    }
}
/**
 * 抽象交通工具实体
 */publicabstractclassAbstractVehicleextendsAbstractModel{
    /**
     * 速度
     */publiclong speed;
}

/**
 * 摩托车实体
 */publicclassMotorcycleVehicleextendsAbstractVehicle{
    @Overridepublicvoidshow(double locationX, double locationY, double angle){
        System.out.println("以" + speed + "迈速度飞驰的摩托车展示完成。展示效果:横向坐标:" + locationX + " 纵向坐标:" + locationY + " 角度:" + angle);
    }
}

/**
 * 吉普车实体
 */publicclassJeepVehicleextendsAbstractVehicle{
    @Overridepublicvoidshow(double locationX, double locationY, double angle){
        System.out.println("以" + speed + "迈速度飞驰的吉普车展示完成。展示效果:横向坐标:" + locationX + " 纵向坐标:" + locationY + " 角度:" + angle);
    }
}
/**
 * 模型的抽象工厂
 */publicabstractclassAbstractModelFactory{
    publicabstract AbstractModel createModel(String modelName);
}

/**
 * 房子的加工工厂
 */publicclassHouseFactoryextendsAbstractModelFactory{
    @Overridepublic AbstractHouse createModel(String modelName){
        switch (modelName) {
            case"红房子":
                returnnew RedHouse();
            case"白房子":
                returnnew WhiteHouse();
        }
        returnnull;
    }
}

/**
 * 交通工具的加工工厂
 */publicclassVehicleFactoryextendsAbstractModelFactory{

    @Overridepublic AbstractVehicle createModel(String modelName){
        switch (modelName) {
            case"吉普车": returnnew JeepVehicle();
            case"摩托车": returnnew MotorcycleVehicle();
        }
        returnnull;
    }

    /**
     * 常见携带速度的交通工具
     */public AbstractVehicle createModelWithSpeed(String modelName, long speed){
        AbstractVehicle vehicle = createModel(modelName);
        if(vehicle != null) {
            vehicle.speed = speed;
        }
        return vehicle;
    }
}
publicclassModelClient {publicstaticvoidmain(String[] args){
        HouseFactory houseFactory = new HouseFactory();
        VehicleFactory vehicleFactory = new VehicleFactory();
        try {
            houseFactory.createModel("白房子").show(3, 2, 5);
            houseFactory.createModel("红房子").show(41, 24, 12);
            System.out.println("-------------------------------");
            vehicleFactory.createModelWithSpeed("摩托车", 233).show(233, 45, 1);
            vehicleFactory.createModelWithSpeed("吉普车", 76).show(345, 234, 32);
        } catch (Exception e) {
            System.out.println("模型未找到");
        }
    }
}

打印结果:

优势:

工厂方法模式的优势就像前面提到的统一管理模型的创建,使调用方更加专注于业务,调用时只需要传入一个key(即demo中的modelName),不需要知道对象创建的过程,降低了模块间耦合度。

劣势:

需要创建工厂类,增加文件数目,没有直接new那么方便。结构设计上不符合开闭原则,每增加一种模型都更改具体工厂中增加一种switch case。

在上文的提到的例子中,需要在工厂里switch case判断创建哪种对象,在大型项目中可以通过泛型、注解等方式解耦,如果大家感兴趣,我后面会专门出一个文章,讲下如何解耦。此外,在复杂业务中,比如房子的类型有几十个,如果全放到一个工厂里制造,会显得特别繁重,这时需要根据房子特征更细粒度的拆分,甚至可能一个工厂对应一种模型。设计模式可以有各种变种,在工作中需要大胆尝试,找到最适合业务的那种。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值