作用:定义一个创建对象的接口,并提供工厂方法将类的实例化推迟到子类,由子类决定要实例化的类是哪一个。
OO原则:
封装变化
针对接口编程优于针对实现编程
依赖抽象,不要依赖具体类
Example:
1、定义一个Flower接口,所有类型的flower都实现自该接口,可以保证类型一致:
public interface Flower {
}
public class ShangHaiFlower implements Flower {
}
public class BeiJingFlower implements Flower {
}
2、定义一个工厂接口,并在里面定义工厂方法以及其他方法:
public abstract class FlowerStore {
public void dealFlower() {
Flower flower;
flower = createFlower();
//do something with the flower;
}
public abstract Flower createFlower(); //创建Flower的工厂方法,工厂方法是抽象的,它依赖子类来处理对象的创建。
}
3、第二步就将创建的行为推迟至子类,我们可以定义多个不同的FlowerStore子类:
public class BeiJingFlowerStore extends FlowerStore {
@Override
public Flower createFlower() {
return new BeiJingFlower();
}
}
public class ShangHaiFlowerStore extends FlowerStore {
@Override
public Flower createFlower() {
return new ShangHaiFlower();
}
}
4、这样我们就可以获取自己想要的Flower了:
public class Main {
public static void main(String[] args) {
FlowerStore flowerStore = new ShangHaiFlowerStore();
Flower flower = flowerStore.createFlower();
FlowerStore flowerStore1 = new BeiJingFlowerStore();
Flower flower1 = flowerStore1.createFlower();
}
}
代码写的比较简单,可能会觉得没什么用,为什么不直接new BeiJingFlowerStore和ShangHaiFlowerStore呢。FlowerStore是一个抽象工厂,它的子类new BeiJingFlowerStore和ShangHaiFlowerStore才是具体的工厂。FlowerStore并不知道会创建什么样的Flower,它只知道它花创建出来并做一些其他的处理就行了。这样的好处在于如果子类变了,比如BeiJingFlowerStore的功能需要修改或者需要其他类型的FlowerStore的时候,我们只需要再加一个定义就行了,而且FlowerStore中还可以定义所有子类型共有的方法如dealFlower,这样将减少代码重复。当然,在实际中可能比较常见的是只有一个具体工厂,但是顶层设计一个抽象工厂还是很有必要的。
另外试想一下如果代码里写的是:
BeiJingFlower flower = new BeiJingFlower();
那么如果后期我不想用BeiJingFlower了呢?我想使用BeiJingFlower1.0怎么办?那就要修改所有代码了。额,怎么感觉说成了多态的好处...哦,不对,这里的重点是工厂方法呀,工厂方法可以根据子类自己的需求创建对象。
可能又有疑问说那这样行不行:
Flower flower = new BeiJingFlower();
嗯,上面这个就是多态,确实解决了想要BeiJingFlower1.0的问题,但是这不是重点啊,工厂模式的重点是要把创建对象的逻辑封装起来,不要在代码里直接用new,而是调用工厂方法来创建。
比如子类中可能有很多需求玫瑰、百合等等等等,这些实例化的逻辑如果直接写在代码里,那以后要加其他花,要修改已有的花就都要修改代码,但是把这些变化封装起来和代码隔离开就便于后期维护了:
public class BeiJingFlowerStore extends FlowerStore {
@Override
public Flower createFlower(String type) {
if(type.equals("rose")) {
return new BeiJingRoseFlower();
}else if(type.equals("lily")) {
return new BeiJingLilyFlower();
}else {
... ...
}
}
}
所以要注意:
1、实例化的代码以后可能会变化,所以封装起来最好
2、要面向接口编程,new一个对象是面向实现的
so,一个工厂方法模式涉及的属性有:抽象工厂类、具体工厂类、抽象产品类、具体产品类。
注意!说的是工厂方法模式,和抽象工厂模式是两回事,虽然它们都属于工厂模式,那下面说一下抽象工厂又是什么:
使用工厂方法可以发现,利用它创建对象时需要扩展一个类并覆盖它的工厂方法。这就是工厂方法,而抽象工厂顾名思义是一个工厂,它和前面写的FlowerStore很像,其实它一般就是使用工厂方法来实现具体工厂,它定义多个方法来创建产品集合。
工厂方法:将实例化的代码解耦或者不确定实例化哪些类
抽象工厂:创建产品家族或者想让相关的产品集合起来
网友评论