1. 工厂方法模式简介
工厂方法模式(Factory Method Pattern)是创建型的设计模式,和简单工厂模式比起来,它去掉了工厂类创建产品对象的方法的静态属性,如此以来,集中在工厂类的压力,便可以由不同的子类来分担。工厂方法模式包括4个角色。
● 抽象产品(Product):它是定义产品的接口,是具体产品的父类,是工厂创建的对象类型,在java中一般有抽象类或者接口来实现。
● 具体产品(ConcreteProduct):它实现了抽象产品接口,一种具体产品由专门的具体工厂创建,具体工厂和具体产品之间一一对应。
● 抽象工厂(Factory):在抽象工厂类中,声明了工厂方法(Factory Method),用于返回一个产品。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口。
● 具体工厂(ConcreteFactory):它是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户端调用,返回一个具体产品类的实例。
2.工厂方法举例
下面我们讲举一个汽车生产的例子,它们的对应关系如下。
类名 | 角色 | 说明 |
---|---|---|
Vehicle | 抽象产品 | 机动车类 |
C200 | 具体产品 | 奔驰C200机动车 |
Bmw330 | 具体产品 | 宝马330机动车 |
VehicleFactory | 抽象工厂 | 机动车工厂 |
BenzFactory | 具体工厂 | 负责生产C200 |
BmwFactory | 具体工厂 | 负责生产Bmw330 |
FactoryMethodMain | 客户端 | 调用发起类 |
Vehicle接口类
/**
* 机动车
* 抽象产品类
*/
public interface Vehicle {
// 所有的机动车都可以跑
void run();
}
C200 产品类
/**
* 奔驰C200
* 具体产品类
*/
public class C200 implements Vehicle {
@Override
public void run() {
System.out.println("C200奔跑在路上。");
}
}
Bmw330 产品类
/**
* 宝马 Bmw330
* 具体产品类
*/
public class Bmw330 implements Vehicle {
public void run() {
System.out.println("Bmw330奔跑在路上。");
}
}
VehicleFactory 抽象工厂类
/**
* 机动车工厂
* 抽象工厂类。 也可以使用abstract class,同时提供模式实现。
*/
public interface VehicleFactory {
// 生产机动车
Vehicle produce();
}
BenzFactory 具体工厂类
/**
* 奔驰工厂,生产C200机动车。
* 具体工厂类。
*/
public class BenzFactory implements VehicleFactory {
@Override
public Vehicle produce() {
return new C200();
}
}
BmwFactory 具体工厂类
/**
* 宝马工厂,生产Bmw330机动车。
* 具体工厂类。
*/
public class BmwFactory implements VehicleFactory {
@Override
public Vehicle produce() {
return new Bmw330();
}
}
FactoryMethodMain 客户端类
public class FactoryMethodMain {
public static void main(String[] args) {
// 不同的工厂,生产不同的机动车
VehicleFactory benzFactory = new BenzFactory();
Vehicle benz = benzFactory.produce();
benz.run();
// 可以通过配置文件的方式,解耦客户端类和具体的工厂类。
VehicleFactory bmwFactoryFactory = new BmwFactory();
Vehicle bmw = bmwFactoryFactory.produce();
bmw.run();
}
}
3. 工厂方法模式总结
优点
工厂方法模式和简单工厂模式相比,继承了优点,弥补了不足;它们生产的产品是同一种产品,使客户端不必知道创建产品对象的细节,甚至是类名。
工厂方法模式充分体现了java的多态性,即工厂角色和产品角色多态,这使得工厂可以自主确定创建何种产品对象。
工厂方法模式具体较好的扩展性,当系统需要加入新产品时,只需要添加了一个具体工厂和具体产品就好,不需要修改抽象工厂类和抽象产品类,也不需要修改其它具体工厂和具体产品类,对客户端也完全没有影响,符合开闭原则。
缺点
每增加一种新产品,就需要多写2个类(1个具体产品+1个具体工厂);同时还提高了系统的抽象度,提高了理解代码的难道。
(完)