首先我们来了解一下设计模式的概念。关于设计模式
Wikipedia 上有那么一段话:
In software engineering, a software design pattern is a general,
reusable solution to a commonly occurring problem within a given
context in software design. It is not a finished design that can be
transformed directly into source or machine code. Rather, it is a
description or template for how to solve a problem that can be used in
many different situations. Design patterns are formalized best
practices that the programmer can use to solve common problems when
designing an application or system.
在软件工程的领域中,软件的设计模式是一种对于经常发生的、在指定上下文范围之内的的一个通用的、可重复使用的解决问题的方案。设计模式不是一个完成了的设计,它不能直接的转换成代码和机器码。而是一种描述或者是模版,这种描述和模版是关于如何解决问题并且可以用于多种不同的场景。设计模式是一种规范化的最佳实践。程序员在设计应用或者系统的时候,可以使用这种实践来解决常见的问题。
翻译过来的文字很长,但是关键的点并不多。
本质上设计模式是在软件的开发过程中的最佳实践,用来解决软件开发中的各种问题。
下面是设计模式的分类和目的:
下面我们详细的说明一下抽象工厂模式(Abstract factory pattern)以及在实际的应用:
目的:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
解决的问题:主要解决的是接口选择的问题。
意思是客户端并不需要知道具体的某一个工厂(继承自抽象工厂)的接口。只需要知道抽象工厂自己提供的接口即可,并不需要对接口进行选择。
在《Java编程思想》的第五章提到了隐藏实施的细节:“在面向对象的设计时,一项基本的考虑是如何将变化着的东西与保持不变的东西分开。”对于库程序员(即利用抽象工厂模式编写库的程序员)而言,并不希望客户程序员(使用那个库的程序员)看到库的具体的实施的细节。举一个简单的例子:
下面的例子是实现一个简单的抽象工厂的例子。
声明一个抽象的汽车工厂,并通过传入车的类型参数来生产不同类型的车:
public abstract class AbstractCarFactory {
public abstract Car produceCars(CarType carType);
}
public enum CarType {
CAR,//普通小汽车
SUV,//SUV
SPORTS_CAR,//运动型小汽车
MPV //多用途汽车
}
声明一个Car 类型的接口,
public interface Car {
void drive();
}
分别让德系车和日系车来实现这个接口:
德系车:
- GermanCar
- GermanSUV
- GermanSportsCar
- GermanMPVCar
public class GermanCar implements Car {
@Override
public void drive() {
System.out.println("German car drive.");
}
}
public class GermanMPVCar implements Car {
@Override
public void drive() {
System.out.println("German MPV drive.");
}
}
public class GermanSportsCar implements Car {
@Override
public void drive() {
System.out.println("German sports car drive.");
}
}
public class GermanSUV implements Car {
@Override
public void drive() {
System.out.println("German SUV drive.");
}
}
日系车:
- JapanCar
- JapanSUV
- JapanSportsCar
- JapanMPVCar
public class JapanCar implements Car {
@Override
public void drive() {
System.out.println("Japanese car drive.");
}
}
public class JapanMPVCar implements Car {
@Override
public void drive() {
System.out.println("Japanese MPV drive.");
}
}
public class JapanSportsCar implements Car {
@Override
public void drive() {
System.out.println("Japanese sports car drive.");
}
}
public class JapanSUV implements Car {
@Override
public void drive() {
System.out.println("Japanese SUV drive.");
}
}
创建两个具体的工厂类:
德系车工厂
public class GermanCarFactory extends AbstractCarFactory {
@Override
public Car produceCars(CarType carType) {
switch (carType) {
case CAR:
return new GermanCar();
case SUV:
return new GermanSUV();
case SPORTS_CAR:
return new GermanSportsCar();
case MPV:
return new GermanMPVCar();
}
return null;
}
}
日系车工厂:
public class JapanCarFactory extends AbstractCarFactory {
@Override
public Car produceCars(CarType carType) {
switch (carType) {
case CAR:
return new JapanCar();
case SUV:
return new JapanSUV();
case SPORTS_CAR:
return new JapanSportsCar();
case MPV:
return new JapanMPVCar();
}
return null;
}
}
最后创建一个FactoryProducer来根据客户传入的国家的类型来创建不同的车系的工厂实例,并通过工厂实例和车的类型来生产不同类型的车:
public class FactoryProducer {
public static AbstractCarFactory getFactory(Nation nation) {
switch (nation) {
case GERMAN:
return new GermanCarFactory();
case JAPANESE:
return new JapanCarFactory();
}
return null;
}
}
我们可以写一个test 类来测试一下:
public class AbstractFactoryDemo {
public static void main(String[] args) {
AbstractCarFactory factory = FactoryProducer.getFactory(Nation.GERMAN);
Car car = factory.produceCars(CarType.SUV);
car.drive();
factory = FactoryProducer.getFactory(Nation.JAPANESE);
car = factory.produceCars(CarType.SPORTS_CAR);
car.drive();
}
}
运行的结果是:
German SUV drive.
Japanese sports car drive.
总结抽象工厂的方法:
Client 即客户端并不需要知道对象的创建的具体的细节,具体的对象是由具体的工厂实例来创建的,客户端也不需要关心。