###1.应用场景 普通工厂方法:
(1) 当一个类不知道它所必须创建的对象的类的时候。
(2) 当一个类希望由它的子类来指定它所创建的对象的时候。
(3) 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
抽象工厂方法:
(1) 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
(2) 这个系统有多于一个的产品族,而系统只消费其中某一产品族。
(3) 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
(4) 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
抽象工厂方法是普通工厂方法的拓展
###2.普通工厂方法示例
// Human
public interface Human {
public void getColor();
public void talk();
}
// WhiteMan
public class WhiteMan implements Human {
@Override
public void getColor() {
System.out.println("skin color is white");
}
@Override
public void talk() {
System.out.println("I'm white");
}
}
// BlackMan
public class BlackMan implements Human {
@Override
public void getColor() {
System.out.println("skin color is black");
}
@Override
public void talk() {
System.out.println("I'm black");
}
}
// AbstractHumanFactory
public abstract class AbstractHumanFactory {
public abstract <T extends Human> T createHuman(Class<T> c);
}
// HumanFactory
public class HumanFactory extends AbstractHumanFactory {
@Override
public <T extends Human> T createHuman(Class<T> c) {
Human human = null;
try {
human = (T) Class.forName(c.getName()).newInstance();
} catch (Exception e) {
System.out.println("造人失败!");
}
return (T)human;
}
}
public static void main(String[] args) {
AbstractHumanFactory factory = new HumanFactory();
Human blackman = factory.createHuman(BlackMan.class);
blackman.getColor();
blackman.talk();
Human whiteman = factory.createHuman(WhiteMan.class);
whiteman.getColor();
whiteman.talk();
}
工厂方法模式是典型的解耦框架。高层模块值需要知道产品的抽象类,其他的实现类都不用关心
Factory实现时完全没有使用到BlackMan和WhiteMan类,且在使用时只需传入相应的产品类名即可,可以Factory不依赖于BlackMan和WhiteMan类实现了解耦。
###3.抽象工厂方法示例
产品相关类
// Human
public interface Human {
public void getColor();
public void talk();
public void getSex();
}
// AbstractBlackHuman
public abstract class AbstractBlackHuman implements Human {
@Override
public void getColor() {
System.out.println("skin is black.");
}
@Override
public void talk() {
System.out.println("I'm black.");
}
}
// AbstractWhiteHuman
public abstract class AbstractWhiteHuman implements Human {
@Override
public void getColor() {
System.out.println("skin is white.");
}
@Override
public void talk() {
System.out.println("I'm white.");
}
}
// MaleBlackHuman
public class MaleBlackHuman extends AbstractBlackHuman {
@Override
public void getSex() {
System.out.println("gender: black male");
}
}
// FemaleBlackHuman
public class FemaleBlackHuman extends AbstractBlackHuman {
@Override
public void getSex() {
System.out.println("gender: black female");
}
}
// MaleWhiteHuman
public class MaleWhiteHuman extends AbstractWhiteHuman {
@Override
public void getSex() {
System.out.println("gender: white male");
}
}
// FemaleWhiteHuman
public class FemaleWhiteHuman extends AbstractWhiteHuman {
@Override
public void getSex() {
System.out.println("gender: white female");
}
}
工厂相关类
// HumanFactory 抽象接口
public interface HumanFactory {
public Human createBlackHuman();
public Human createWhiteHuman();
}
// FemaleFactory
public class FemaleFactory implements HumanFactory {
@Override
public Human createBlackHuman() {
return new FemaleBlackHuman();
}
@Override
public Human createWhiteHuman() {
return new FemaleWhiteHuman();
}
}
// MaleFactory
public class MaleFactory implements HumanFactory {
@Override
public Human createBlackHuman() {
return new MaleBlackHuman();
}
@Override
public Human createWhiteHuman() {
return new MaleWhiteHuman();
}
}
抽象工厂方法的缺点
抽象工厂方法的主要缺点是产品族拓展非常困难,当我们需要增加一个YellowHuman类时需要改动的类太多,也即纵向拓展难(相较而言横向拓展则非常容易,如添加双性人的性别 intersex只需添加相应的产品类以及添加新的工厂类而无需或极少修改原来的类)。