目录
3、工厂方法模式 3.1 介绍 3.2 工厂的多元化与专业化 3.3 游戏角色建模(建模) 3.4 简单工厂不简单(实例化、初始化) 3.5 制定工业制造标准 3.6劳动分工
3、工厂方法模式
3.1 介绍
程序设计中的工厂类往往是对对象构造、实例化、初始化过程的封装 ,而工厂方法(Factory Method)则可以升华为一种设计模式 它对工厂制造方法 进行接口规范化 ,以允许子类工厂决定具体制造哪类产品的实例,最终降低系统耦合,使系统的可维护性、可扩展性等得到提升 测试类文件,下面开始进行示例(空战游戏示例)。
3.2 工厂的多元化与专业化
要制造产品(实例化对象)就得用到关键字“new”,例如“Plane plane = newPlane();”,或许还会有一些复杂的初始化代码(硬编码) 当我们不必关心产品的制造过程(实例化、初始化),而将这个任务交由相应的工厂来全权负责时,工厂最终能交付产品供我们使用即可 工厂内部封装的生产逻辑对外部来说像一个黑盒子,外部不需要关心工厂内部细节,外部类只管调用即可 多元化的生产模式,不同的产品可以交由不同的专业工厂来生产 ,例如皮鞋由皮鞋工厂来制造,汽车则由汽车工厂来制造,专业化分工明确
3.3 游戏角色建模(建模)
敌人的种类有飞机和坦克:有共同的属性或行为,描述位置状态的坐标,以及一个展示(绘制)方法 使用抽象类Enemy来定义所有敌人的父类
package factory. entity ;
public abstract class Enemy {
protected int x;
protected int y;
public Enemy ( int x, int y) {
this . x = x;
this . y = y;
}
public abstract void show ( ) ;
}
具体子类实现,也就是敌机类Airplane和坦克类Tank
package factory. entity ;
import factory. entity. Enemy ;
public class Airplane extends Enemy {
public Airplane ( int x, int y) {
super ( x, y) ;
}
@Override
public void show ( ) {
System . out. println ( "绘制飞机于上层图层,出现坐标:" + x + "," + y) ;
System . out. println ( "飞机向玩家发起攻击……" ) ;
}
}
package factory. entity ;
import factory. entity. Enemy ;
public class Tank extends Enemy {
public Tank ( int x, int y) {
super ( x, y) ;
}
@Override
public void show ( ) {
System . out. println ( "绘制坦克于下层图层,出现坐标:" + x + "," + y) ;
System . out. println ( "坦克向玩家发起攻击……" ) ;
}
}
3.4 简单工厂不简单(实例化、初始化)
产品建模完成 后,就应该考虑如何实例化和初始化 这些敌人了 客户端测试类,new 实例化和初始化敌机类
package factory. simpleFactory ;
import factory. entity. Airplane ;
import factory. entity. Tank ;
import java. util. Random ;
public class Client {
public static void main ( String [ ] args) {
test1_default ( ) ;
}
private static void test1_default ( ) {
int screenWidth = 100 ;
System . out. println ( "游戏开始" ) ;
Random random = new Random ( ) ;
int x = random. nextInt ( screenWidth) ;
Airplane airplane = new Airplane ( x, 0 ) ;
airplane. show ( ) ;
x = random. nextInt ( screenWidth) ;
Tank tank = new Tank ( x, 0 ) ;
tank. show ( ) ;
}
}
然而,制造随机出现的敌人这个动作貌似不应该出现在客户端类中
试想如果我们还有其他敌人也需要构造的话,那么同样的代码就会再次出现,尤其是当初始化越复杂的时候重复代码就会越多 如此耗时费力,何不把这些实例化逻辑抽离出来作为一个工厂类
package factory. simpleFactory ;
import factory. entity. Airplane ;
import factory. entity. Enemy ;
import factory. entity. Tank ;
import java. util. Random ;
public class SimpleFactory {
private int screenWidth;
private Random random;
public SimpleFactory ( int screenWidth) {
this . screenWidth = screenWidth;
this . random = new Random ( ) ;
}
public Enemy create ( String type) {
int i = random. nextInt ( screenWidth) ;
Enemy en = null ;
switch ( type) {
case "Airplane" :
en = new Airplane ( i, 0 ) ;
break ;
case "Tank" :
en = new Tank ( i, 0 ) ;
break ;
}
return en;
}
}
private static void test2_simpleFactory ( ) {
System . out. println ( "游戏开始" ) ;
SimpleFactory simpleFactory = new SimpleFactory ( 100 ) ;
simpleFactory. create ( "Airplane" ) . show ( ) ;
simpleFactory. create ( "Tank" ) . show ( ) ;
}
简单工厂类SimpleFactory将之前在客户端测试类里制造敌人的代码挪过来
如此一来,制造敌人这个任务就全权交由【简单工厂】来负责了,于是客户端便可以直接从简单工厂取用敌人了 虽然客户端中不再直接出现对产品实例化的代码,但羊毛出在羊身上,制造逻辑只是被换了个地方 ,挪到了简单工厂中而已 并且客户端还要告知产品种类才能产出,这无疑是另一种意义上的耦合
3.5 制定工业制造标准
针对复杂多变的生产需求,将简单工厂的制造方法进行拆分 ,构建起抽象化、多态化 的生产模式 对各种各样的生产方式(工厂方法)进行抽象,首先定义一个工厂接口,以确立统一的工业制造标准 工厂接口: 确立统一标准,是工厂方法模式的核心
package factory. factoryMethod ;
import factory. entity. Enemy ;
public interface Factory {
Enemy createEnemy ( int screenWidth) ;
}
实现工厂类,关键字implements实现工厂接口Factory
飞机工厂制造飞机 坦克工厂制造坦克 如果需要扩展:基于此模式继续我们的扩展即可: 创建工厂类,同样实现工厂方法接口
package factory. factoryMethod ;
import factory. entity. Airplane ;
import factory. entity. Enemy ;
import java. util. Random ;
public class AirplaneFactory implements Factory {
@Override
public Enemy createEnemy ( int screenWidth) {
Random random = new Random ( ) ;
return new Airplane ( random. nextInt ( screenWidth) , 0 ) ;
}
}
package factory. factoryMethod ;
import factory. entity. Enemy ;
import factory. entity. Tank ;
import java. util. Random ;
public class TankFactory implements Factory {
@Override
public Enemy createEnemy ( int screenWidth) {
Random random = new Random ( ) ;
return new Tank ( random. nextInt ( screenWidth) , 0 ) ;
}
}
package factory. factoryMethod ;
import factory. entity. Boss ;
import factory. entity. Enemy ;
public class BossFactory implements Factory {
@Override
public Enemy createEnemy ( int screenWidth) {
return new Boss ( screenWidth/ 2 , 0 ) ;
}
}
每个工厂的生产策略或方式都具备自己的产品特色,不同的产品需求都能找到相应的工厂来满足,即便没有,我们也可以添加新工厂来解决 使系统具有良好的兼容性和可扩展性
3.6劳动分工
只需添加相应的工厂类,无须再对现有代码做任何更改 工厂方法模式 可以被看作由简单工厂演化而来的高级版,后者才是真正的设计模式在工厂方法模式中,不仅产品需要分类,工厂同样需要分类 工厂方法模式的各角色定义
Product(产品):所有产品的顶级父类,可以是抽象类或者接口。如:Enemy ConcreteProduct(子产品):由产品类Product派生出的产品子类,可以有多个产品子类。如:Airplane、Tank、Boss Factory(工厂接口):定义工厂方法的工厂接口 ,当然也可以是抽象类 ,它使顶级工厂制造方法抽象化、标准统一化 。如:Factory ConcreteFactory(工厂实现):实现了工厂接口的工厂实现类,并决定工厂方法中具体返回哪种产品子类的实例。如:AirplaneFactory、AirplaneFactory、BossFactory 明确合理的劳动分工才能真正地促进生产效率的提升