一、 工厂方法模式介绍
工厂方法模式 , 是创建设计模式之一 。 工厂方法模式是一种构建简单的模式 , 其实我们平时开发中用的也是比较广泛 , 先来看一下工厂方法的模式定义 。
二、工厂方法模式的定义
Define an interface for creating an object,but let subclasses decide which class toinstantiate.Factory Method lets a class defer instantiation to subclasses.
(定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。)
三、工厂方法模式的使用场景
在任何需要生成复杂对象的地方 , 都可以使用工厂方法模式 。
当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式
复杂对象适合使用工厂模式 , 用 new 就可以完成创建的对象无需使用工厂模式
假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。
四、实战
代码 :
package com.example.liangshaoteng.myapplication.shejimoshizicandao.danyizhizhe.gongchangfangfamoshi;
/**
* Created by liangshaoteng on 17-7-21.
*/
public interface Human {
//每个人种的皮肤都有相应的颜色
public void getColor();
//人类会说话
public void talk();
}
接口Human是对人类的总称,每个人种都至少具有两个方法,黑色人种、黄色人种、白色人种
package com.example.liangshaoteng.myapplication.shejimoshizicandao.danyizhizhe.gongchangfangfamoshi;
/**
* Created by liangshaoteng on 17-7-21.
*/
public class BlackHuman implements Human {
@Override
public void getColor() {
System.out.println("黑色人种的皮肤颜色是黑色的!");
}
@Override
public void talk() {
System.out.println("黑人会说话,一般人听不懂。");
}
}
package com.example.liangshaoteng.myapplication.shejimoshizicandao.danyizhizhe.gongchangfangfamoshi;
/**
* Created by liangshaoteng on 17-7-21.
*/
public class YellowHuman implements Human {
@Override
public void getColor() {
System.out.println("黄色人种的皮肤颜色是黄色的!");
}
@Override
public void talk() {
System.out.println("黄色人种会说话,一般说的都是双字节。");
}
}
package com.example.liangshaoteng.myapplication.shejimoshizicandao.danyizhizhe.gongchangfangfamoshi;
/**
* Created by liangshaoteng on 17-7-21.
*/
public class WhiteHuman implements Human {
@Override
public void getColor() {
System.out.println("白色人种的皮肤颜色是白色的!");
}
@Override
public void talk() {
System.out.println("白色人种会说话,一般都是但是单字节。");
}
}
注意,我们在这里采用了泛型(Generic),通过定义泛型对createHuman的输入参数产
生两层限制:
● 必须是Class类型;
● 必须是Human的实现类。
其中的"T"表示的是,只要实现了Human接口的类都可以作为参数,泛型是JDK 1.5中的
一个非常重要的新特性,它减少了对象间的转换,约束其输入参数类型,对Collection集合下
的实现类都可以定义泛型。
package com.example.liangshaoteng.myapplication.shejimoshizicandao.danyizhizhe.gongchangfangfamoshi;
import static android.icu.lang.UCharacter.GraphemeClusterBreak.T;
/**
* Created by liangshaoteng on 17-7-21.
*/
public abstract class AbstractHumanFactory {
public abstract <T extends Human> T createHuman(Class<T> c);
}
通过反射的形式来创建实例
package com.example.liangshaoteng.myapplication.shejimoshizicandao.danyizhizhe.gongchangfangfamoshi;
/**
* Created by liangshaoteng on 17-7-21.
*/
public class HumanFactory extends AbstractHumanFactory {
private Human human;
@Override
public <T extends Human> T createHuman(Class<T> c) {
try {
human = (Human) c.forName(c.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return (T) human;
}
}
public class NvWa {
public static void main(String[] args) {
//声明阴阳八卦炉
AbstractHumanFactory YinYangLu = new HumanFactory();
System.out.println("--造出的第一批人是白色人种--");
Human whiteHuman = YinYangLu.createHuman(WhiteHuman.class);
whiteHuman.getColor();
whiteHuman.talk();
System.out.println("\n--造出的第二批人是黑色人种--");
Human blackHuman = YinYangLu.createHuman(BlackHuman.class);
blackHuman.getColor();
blackHuman.talk();
System.out.println("\n--造出的第三批人是黄色人种--");
Human yellowHuman = YinYangLu.createHuman(YellowHuman.class);
yellowHuman.getColor();
yellowHuman.talk();
}
}
五、升级为多个工厂类
当我们在做一个比较复杂的项目时,经常会遇到初始化一个对象很耗费精力的情况,所有的产品类都放到一个工厂方法中进行初始化会使代码结构不清晰。例如,一个产品类有5个具体实现,每个实现类的初始化(不仅仅是new,初始化包括new一个对象,并对对象设置一定的初始值)方法都不相同,如果写在一个工厂方法中,势必会导致该方法巨大无比,那该怎么办?
考虑到需要结构清晰,我们就为每个产品定义一个创造者,然后由调用者自己去选择与哪个工厂方法关联。
多工厂模式的抽象工厂类
public abstract class AbstractHumanFactory {
public abstract Human createHuman();
}
注意 抽象方法中已经不再需要传递相关参数了,因为每一个具体的工厂都已经非常明
确自己的职责:创建自己负责的产品类对象。
黑种人工厂
public class BlackHumanFactory extends AbstractHumanFactory {
public Human createHuman() {
return new BlackHuman();
}
}
黄种人工厂
public class YellowHumanFactory extends AbstractHumanFactory {
public Human createHuman() {
return new YellowHuman();
}
}
白种人工厂
public class whiteHumanFactory extends AbstractHumanFactory {
public Human createHuman() {
return new WhiteHuman();
}
}
public class NvWa {
public static void main(String[] args) {
//女娲第一次造人,火候不足,于是白色人种产生了
System.out.println("--造出的第一批人是白色人种--");
Human whiteHuman = (new WhiteHumanFactory()).createHuman();
whiteHuman.getColor();
whiteHuman.talk();
//女娲第二次造人,火候过足,于是黑色人种产生了
System.out.println("\n--造出的第二批人是黑色人种--");
Human blackHuman = (new BlackHumanFactory()).createHuman();
blackHuman.getColor();
blackHuman.talk();
//第三次造人,火候刚刚好,于是黄色人种产生了
System.out.println("\n--造出的第三批人是黄色人种--");
Human yellowHuman = (new YellowHumanFactory()).createHuman();
yellowHuman.getColor();
yellowHuman.talk();
}
}
总结
无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。
所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。