前因:如果创建一个对象需要一系列复杂的初始化操作,比如需要关联其他成员对象、查配置文件、查数据库表…
如果将这些东西写在构造函数里面,那么代码会变得很长很长,大大降低了程序的可读性。
这个时候,我们可以增加一个特殊的类—工厂类,专门负责对象的创建工作。
public class Mask {
//构造函数
public Mask(){
// .....
// 100行初始化代码
}
}
public class MaskFactory {
public Mask createMask() {
Mask mask = new Mask();
// .....
// 100行初始化代码
return mask;
}
}
假如这个口罩分为高端口罩和低端口罩
public interface IMask {
void show();
}
public class HighEndMask implements IMask {
@Override
public void show() {
System.out.println("我是高端口罩");
}
}
public class LowEndMask implements IMask {
@Override
public void show(){
System.out.println("我的低端口罩");
}
}
为了区分,我们可以传入不同的参数,根据参数返回不同的口罩
public class MaskFactory{
public IMask createMask(String type) {
IMask mask = null;
if("高端口罩".equals(type)){
mask = new HighEndMask();
// .....
// HighEndMask的100行初始化代码
}else if("低端口罩".equals(type)){
mask = new LowEndMask();
// .....
// LowEndMask的100行初始化代码
}
return mask;
}
}
使用
public class Test {
public static void main(String[] args) {
MaskFactory factory = new MaskFactory();
IMask maskA = factory.createMask("高端口罩");
IMask maskB = factory.createMask("低端口罩");
maskA.show();
maskB.show();
}
}
像这样通过工厂类创建对象,并且根据传入参数决定具体子类对象的做法,就是简单工厂模式(Simple Factory Pattern)
但是,如果增加新的口罩类别,就要修改这个工厂模式了,不符合开闭原则。因此,我们可以针对每一个口罩类创建对应的工厂类,这些工厂类分别实现抽象的工厂接口,这样我们只要实例化不同的工厂类,调用创建方法,得到的就是对应的口罩对象。(多态)
public interface IMaskFactory {
IMask createMask();
}
public class HighEndFactory implements IMaskFactory{
@Override
public IMask createMask() {
IMask mask = new HighEndMask();
// .....
// HighEndMask的100行初始化代码
return mask;
}
}
public class LowEndFactory implements IMaskFactory{
@Override
public IMask createMask() {
IMask mask = new LowEndMask();
// .....
// LowEndMask的100行初始化代码
return mask;
}
}
在代码中,工厂类变成了抽象的接口,高端口罩工厂和低端口罩工厂这两个子类分别实现了该接口。
在客户端,想要创建什么样的口罩对象,只需实例化不同的工厂子类,调用相同的创建方法,无需再传入参数:
public class Test {
public static void main(String[] args) {
IMaskFactory factoryA = new LowEndFactory();
IMaskFactory factoryB = new HighEndFactory();
IMask maskA = factoryA.createMask();
IMask maskB = factoryB.createMask();
maskA.show();
maskB.show();
}
}
这就是工厂方法模式(Factory Method Pattern)
如果业务涉及的子类越来愈多,不可能每一个都要创建一个子类
这个时候可以对应的进行分组:
首先看一下产品类的代码,口罩和防护服是两个抽象接口,分别拥有高端和低端两个实现类:
public interface IMask {
void showMask();
}
public class LowEndMask implements IMask {
@Override
public void showMask(){
System.out.println("我的低端口罩");
}
}
public class HighEndMask implements IMask {
@Override
public void showMask() {
System.out.println("我是高端口罩");
}
}
public interface IProtectiveSuit {
void showSuit();
}
public class LowEndProtectiveSuit implements IProtectiveSuit {
@Override
public void showSuit() {
System.out.println("我是低端防护服");
}
}
public class HighEndProtectiveSuit implements IProtectiveSuit {
@Override
public void showSuit() {
System.out.println("我是高端防护服");
}
}
接下来是工厂类,由于产品分成了高端和低端两大组,工厂也相应分成了高端工厂和低端工厂,各自负责组内产品的创建:
public interface IFactory {
//创建口罩
IMask createMask();
//创建防护服
IProtectiveSuit createSuit();
}
public class LowEndFactory implements IFactory {
@Override
public IMask createMask() {
IMask mask = new LowEndMask();
// .....
// LowEndMask的100行初始化代码
return mask;
}
@Override
public IProtectiveSuit createSuit() {
IProtectiveSuit suit = new LowEndProtectiveSuit();
// .....
// LowEndProtectiveSuit的100行初始化代码
return suit;
}
}
public class HighEndFactory implements IFactory {
@Override
public IMask createMask() {
IMask mask = new HighEndMask();
// .....
// HighEndMask的100行初始化代码
return mask;
}
@Override
public IProtectiveSuit createSuit() {
IProtectiveSuit suit = new HighEndProtectiveSuit();
// .....
// HighEndProtectiveSuit的100行初始化代码
return suit;
}
}
最后是客户端代码,通过实例化不同的工厂子类,调用不同的创建方法,可以创建出不同的产品:
public class Test {
public static void main(String[] args) {
IFactory factoryA = new LowEndFactory();
IFactory factoryB = new HighEndFactory();
//创建低端口罩
IMask maskA = factoryA.createMask();
//创建高端口罩
IMask maskB = factoryB.createMask();
//创建低端防护服
IProtectiveSuit suitA = factoryA.createSuit();
//创建高端防护服
IProtectiveSuit suitB = factoryB.createSuit();
maskA.showMask();
maskB.showMask();
suitA.showSuit();
suitB.showSuit();
}
}
像这样把产品类分组,组内不同产品对应于同一工厂类不同方法的涉及模式,就是抽象工厂模式(Abstract Factory Pattern)
参考: