工厂方法模式
Define an interface for creating an object,but let subclasses decide whichclass to instantiate.Factory Method lets a class defer instantiation tosubclasses.(定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
抽象产品类
拆解一下这段定义,第一步,定义一个用于创建对象的接口,我们以流传已广的种水果举例,水果的通用特性取颜色和名称,因为是通用特性,所以此处水果是一个接口。
public interface Fruit {
void getFruitName();
void getFruitColor();
}
为了简化过程,此处只加入苹果和香蕉两种,分别实现水果的接口。
public class Banana implements Fruit {
@Override
public void getFruitName() {
System.out.println("this is banana");
}
@Override
public void getFruitColor() {
System.out.println("this is yellow");
}
}
public class Apple implements Fruit{
@Override
public void getFruitName() {
System.out.println("this is apple");
}
@Override
public void getFruitColor() {
System.out.println("this is red");
}
}
创建抽象工厂
既然水果的接口有了,那么该种水果了,至于种什么水果,这里不需要操心,那是实现类中的事情。
public abstract class AbsCreateFruit {
public abstract <T extends Fruit> T createFruit(Class<T> c);
}
定义一个抽象接口,加入一个抽象的种水果的方法交给子类去实现,子类通过反射获取到自己想实现的水果即可。
实现工厂
public class CreateFruit extends AbsCreateFruit {
Fruit fruit = null;
@Override
public <T extends Fruit> T createFruit(Class<T> c) {
try {
fruit = (Fruit) Class.forName(c.getName()).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
return (T)fruit;
}
}
利用反射获取到需要种的水果,完成创建工作。
最后的实现
public class GrowFruit {
public static void main(String[] args) {
CreateFruit createFruit = new CreateFruit();
Fruit apple = createFruit.createFruit(Apple.class);
apple.getFruitColor();
apple.getFruitName();
Fruit banana = createFruit.createFruit(Banana.class);
banana.getFruitName();
banana.getFruitColor();
}
}
在设计模式之禅中给出了通用类图
- Product :负责定义产品的公共的特性
- ConcreteProduct :具体的产品
- Create :抽象创建类,也就是抽象工厂
- ConcreateCreator : 具体的实现类
工厂方法模式的优点
一、封装良好,结构清晰
需要创建一个具体的产品,只需要知道产品类的名称即可,降低了模块之间的耦合。
二、扩展性优秀
如果需要添加一个新的水果品种,只需要加入一个新的实现类,工厂类本身是不需要任何修改的。符合对修改关闭,对增加开发的原则。
三、屏蔽产品类
产品类的实现如何变化,调用者都不需要关心,它只需要关心产品的接口,只要接口保持不变,系统中的上层模块就不要发生变化
简单工厂模式
在首次接触工厂模式的时候,第一次见到的大概就是简单工厂模式,工厂模式就是在上述框架的基础上去掉了抽象的创建类,使用了方法,简化了代码逻辑,但是出现了扩展困难的问题,也不符合开闭原则。
实现类和场景类修改如下
public class CreateFruit {
public static <T extends Fruit> T createFruit(Class<T> c) {
Fruit fruit = null;
try {
fruit = (Fruit) Class.forName(c.getName()).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
return (T)fruit;
}
}
public class GrowFruit {
public static void main(String[] args) {
Fruit apple = CreateFruit.createFruit(Apple.class);
apple.getFruitColor();
apple.getFruitName();
Fruit banana = CreateFruit.createFruit(Banana.class);
banana.getFruitName();
banana.getFruitColor();
}
}
多工厂类
每一个具体的产品类都会对应一个创建者,每一个创建者都会独立负责创建对应的产品对象,符合单一职责。
于是,水果的抽象类可以修改如下
public abstract class AbsCreateFruit {
public abstract Fruit createFruit();
}
工厂实现
public class AppCreateFruit extends AbsCreateFruit {
@Override
public Fruit createFruit() {
return new Apple();
}
}
最后的调用
public class GrowFruit {
public static void main(String[] args) {
Fruit apple = new AppCreateFruit().createFruit();
apple.getFruitColor();
apple.getFruitName();
}
}
优势
创建简单,结构清楚,通俗易懂
参考和引用
设计模式之禅