工厂是制造产品的,那这个工厂具体制造什么样的产品则根据各个产业领域不同而不同。但是工厂对外的只是产品,具体产品如何生产对用户来说是透明的。
下面列出一副图来描述工厂方法的结构:
上述图中Product是接口部分.
ConcreteProduct是具体的产品接口实现。
FactoryMethod是父类工厂。
ConceteCreateor来返回ConcreteProduct实例。
下图是工厂方法简单原型图:
下面我列举实际项目中的工厂方法使用例子:
对于移动平台的项目,尤其针对android会有很多渠道,比如91比如360等等,然后这些渠道都有自己的特点,因此在我们项目当中需要为这些不同的平台分别定制,但是产品的核心功能是不变的,由此需求,工厂方法设计再合适不过了。
下面是例子工程结构图:
上图中的com.zsh.lib 是我们的核心代码包,com.zsh.test是渠道部分。
GameManager负责整合产品的核心调度:具体实现如下
package com.zsh.lib;
public class GameManager {
private UserFactory mUserFactory;
private GameManager() {
}
private static GameManager mInstance = null;
static GameManager get_instance() {
if (mInstance == null) {
return mInstance = new GameManager();
}
return mInstance;
}
void init() {
}
public UserFactory getmUserFactory() {
return mUserFactory;
}
public void setmUserFactory(UserFactory mUserFactory) {
this.mUserFactory = mUserFactory;
}
}
GameManager包含创建工厂方法以便获得真实的产品(既各渠道平台自定义的实现)
IUserBehavior 是定义好的渠道平台需要实现的接口,下面是例子当中需要实现的接口:
package com.zsh.lib;
public interface IUserBehavior {
void init();
void stand();
void run();
void attack();
}
MainEnter是项目核心的主入口,程序启动的时候会通过平台来调用这个接口进入项目逻辑。
package com.zsh.lib;
import com.zsh.lib.GameManager;
public class MainEnter {
public void init() {
GameManager.get_instance().setmUserFactory(this.getUserFactory());
GameManager.get_instance().getmUserFactory().createUserBehavior()
.attack();
GameManager.get_instance().getmUserFactory().createUserBehavior()
.run();
GameManager.get_instance().getmUserFactory().createUserBehavior()
.stand();
}
protected UserFactory getUserFactory() {
return new UserFactory();
}
}
上面的init函数中调用三个具体实现,在这里只是作为例子才放在这边调用,在正真的项目中需要放到功能所需的位置来调用对应的方法。
UserFactory 工厂方法定义的具体实现:package com.zsh.lib;
import com.zsh.lib.IUserBehavior;
public class UserFactory {
public IUserBehavior createUserBehavior()
{
return null;
}
//TODO some other function
}
上面列的一些类是我们产品的核心部分,包括定义的外部需要实现的接口,以及提供的工厂方法原型。
接下来介绍一下我们渠道的主入口即程序启动的入口。
FactoryMethod继承自在lib中定义好的工厂类,然后具体实现。
package com.zsh.test;
import com.zsh.lib.IUserBehavior;
import com.zsh.lib.UserFactory;
public class FactoryMethod extends UserFactory{
private PlayerBehavior mPlayerBehavior;
public IUserBehavior createUserBehavior()
{
if(mPlayerBehavior==null)
{
mPlayerBehavior = new PlayerBehavior();
mPlayerBehavior.init();
return mPlayerBehavior;
}
return mPlayerBehavior;
}
}
FactoryMethod会真正创建所需要的行为。
PlayerBehavior实现lib中定好的接口
package com.zsh.test;
import com.zsh.lib.IUserBehavior;
public class PlayerBehavior implements IUserBehavior{
@Override
public void init() {
}
@Override
public void stand() {
// TODO Auto-generated method stub
System.out.println("stand");
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("run");
}
@Override
public void attack() {
// TODO Auto-generated method stub
System.out.println("attack");
}
}
最后是平台的主入口:
package com.zsh.test;
import com.zsh.lib.MainEnter;
import com.zsh.lib.UserFactory;
public class PublicMain extends MainEnter{
public static void main(String args[])
{
PublicMain publicMain = new PublicMain();
publicMain.init();
}
public void init()
{
super.init();
}
@Override
protected UserFactory getUserFactory()
{
return new FactoryMethod();
}
}
使用工厂方法模式需要考虑两种不同的情况。1)UserFactory是一个抽象类不提供它所声明的工厂方法实现。2)UserFactory是一个具体的类为工厂方法提供一个缺省的而实现。因此这种情况需要用户自己定义并实现工厂方法。上述例子中使用了这种情况。
第一种情况需要子类来定义实现,避免了不得不实例化不可预见类的问题,第二种情况则展现了其灵活性、可扩展性因此,在上述例子这种需求项目中采用了这种情况。