一、工厂方法模式
说到工厂方法模式,先来了解一下简单工厂模式吧。
在这里引用一下《JAVA与模式》的概念:简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。
我们来做一个Demo来简述一下
首先创建一个Fruit(水果)接口,并提供一个提供水果的方法:
public interface Fruit {
public void provideFruit();
}
然后创建两个实现类Apple 和 Pear 实现Fruit接口,实现提供水果的方法:
public class Apple implements Fruit{
@Override
public void provideFruit() {
// TODO Auto-generated method stub
System.out.println("提供苹果");
}
}
public class Pear implements Fruit{
@Override
public void provideFruit() {
// TODO Auto-generated method stub
System.out.println("提供梨子");
}
}
然后创建一个工厂类FruitManager,并提供一个可以获得水果对象的静态方法factory
public class FruitManager {
public static Fruit factory(String type) {
if("苹果".equals(type)) {
return new Apple();
}else if("梨".equals(type)) {
return new Pear();
}
throw new RuntimeException("没有你要的水果哎");
}
}
下面写一个测试类,根据不同的类型去拿到不同的水果对象,并调用提供水果的方法:
public class GetFruit {
public static void main(String[] args) {
Fruit apple = FruitManager.factory("苹果");
Fruit pear = FruitManager.factory("梨");
apple.provideFruit();
System.out.println("-----");
pear.provideFruit();
}
}
控制台打印:
简单工厂模式的优点
模式的核心是工厂类。这个类含有必要的逻辑判断,可以根据不同的类型去获得不同的水果供应对象,免除了调用者直接创建对象的责任,实现了对责任的分割。
简单工厂模式的缺点
这个工厂类集中了所有的创建逻辑,当有复杂的多层次等级结构时,所有的业务逻辑都在这个工厂类中实现。什么时候它不能工作了,整个系统都会受到影响。
工厂方法模式概述
工厂方法模式是类的创建模式,又叫做虚拟构造子(Virtual Constructor)模式或者多态性工(Polymorphic Factory)模式。
工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。
个人理解的工厂方法模式使用场景
当使用简单工厂模式时,只有一个工厂类,在需要处理的逻辑比较复杂,工厂类中的代码会非常的臃肿,杂乱,以后再有其他需求,难以改动,就需要用工厂方法模式来处理。
在工厂方法模式中,不再由一个工厂类去负责所有的对象产生,而是把它抽象化,交给它的子类去进行创建对象,不去接触细节逻辑。这种方式可以让系统在不修改具体类的情况下,添加新的需求。
从上图可以看出,这个使用的工厂方法模式的系统涉及到以下角色:
抽象工厂(ExportFactory)角色:担任这个角色的是工厂方法模式的核心,任何在模式中创建对象的工厂类必须实现这个接口。在实际的系统中,这个角色也常常使用抽象类实现。
具体工厂(ExportHtmlFactory、ExportPdfFactory)角色:担任这个角色的是实现了抽象工厂接口的具体JAVA类。具体工厂角色含有与业务密切相关的逻辑,并且受到使用者的调用以创建导出类(如:ExportStandardHtmlFile)。
抽象导出(ExportFile)角色:工厂方法模式所创建的对象的超类,也就是所有导出类的共同父类或共同拥有的接口。在实际的系统中,这个角色也常常使用抽象类实现。
具体导出(ExportStandardHtmlFile等)角色:这个角色实现了抽象导出(ExportFile)角色所声明的接口,工厂方法模式所创建的每一个对象都是某个具体导出角色的实例。
还是进行一个实例去理解一下:
创建一个核心工厂接口ExportFruitFactory,并提供一个工厂抽象方法:
public interface FruitFactory {
public Fruit factory(String type);
}
用刚才的Fruit接口以及创建子类RedApple,YellowApple,GoodPear,BadPear
之后创建具体的工厂角色,并实现factory方法:
public class AppleFactory implements FruitFactory{
@Override
public Fruit factory(String type) {
if("red".equals(type)){
return new RedApple();
}else if("yellow".equals(type)) {
return new YellowApple();
}
throw new RuntimeException("找不到类型");
}
}
public class PearFactory implements FruitFactory{
@Override
public Fruit factory(String type) {
if("good".equals(type)){
return new GoodPear();
}else if("bad".equals(type)) {
return new BadPear();
}
throw new RuntimeException("找不到类型");
}
}
创建测试类,创建需要的工厂对象,再调用factory创建对象,并调动provideFruit方法测试。
public class GetFruit {
public static void main(String[] args) {
FruitFactory appleFactory = new AppleFactory();
Fruit fruit = appleFactory.factory("red");
fruit.provideFruit();
}
}
可以看出工厂方法模式和简单工厂模式的一个不同点,简单工厂的核心类是具体的类,而工厂方法模式的核心类是一个抽象的接口。工厂方法模式是可以退化成简单工厂模式的,如果很确定一个程序只需要一个工厂类,那么大可以将核心类的实现类和接口合并为一个具体类,如果可能出现更多的需求类型,那么使用工厂方法模式会更加灵活,也就是开闭原则的 提供扩展,不提供修改。
不过,一般一个应用程序是不是一个人开发的,如果别人去调用/维护的人是别人,应该降低的耦合度,设计更灵活。如果需求变动,你想去新增/修改一些功能,别人在调用的时候不用做任何修改,便于维护。
下一篇 抽象工厂模式