抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
创建一系列的产品对象,而且这一系列对象是构成新的对象所需要的组成部分,也就是这一系列被创建的对象相互之间是有关联的。
解决这个问题的一个解决方案就是抽象工厂模式。在这个模式里,会定义一个抽象工厂,在里边虚拟的创建客户端需要的这一系列对象,所谓虚拟的就是定义创建这些对象的抽象方法,并不去真正的实现,然后由具体的抽象工厂的子类来提供这一系列对象的创建。这样一来,可以为同一个抽象工厂提供很多不同的实现,那么创建的这一系列对象也就不同了。
假设鼠标和键盘是我们需要的产品,生产鼠标和键盘的戴尔和联想是我们的工厂。
1、创建鼠标接口和具体的鼠标实现类
Mouse.java
/**
* 鼠标接口
*/
public interface Mouse {
/**
* 点击鼠标
*/
public void click();
}
DellMouse.java
/**
* 戴尔鼠标
*/
public class DellMouse implements Mouse {
@Override
public void click() {
System.out.println("使用戴尔鼠标进行点击...");
}
}
LenovoMouse.java
/**
* 联想鼠标
*/
public class LenovoMouse implements Mouse {
@Override
public void click() {
System.out.println("使用联想鼠标进行点击...");
}
}
2、创建键盘接口和具体的键盘实现类
Keyboard.java
/**
* 键盘接口
*/
public interface Keyboard {
/**
* 使用键盘打字
*/
public void type();
}
DellKeyboard.java
/**
* 戴尔键盘
*/
public class DellKeyboard implements Keyboard {
@Override
public void type() {
System.out.println("使用戴尔键盘打字...");
}
}
LenovoKeyboard.java
/**
* 联想键盘
*/
public class LenovoKeyboard implements Keyboard {
@Override
public void type() {
System.out.println("使用联想键盘打字...");
}
}
3、创建获取鼠标对象和键盘对象的抽象工厂
AbstractFactory.java
/**
* 抽象工厂的接口,声明创建抽象产品对象的操作
*/
public interface AbstractFactory {
/**
* 创建鼠标对象
* @return
*/
public Mouse createMouse();
/**
* 创建键盘对象
* @return
*/
public Keyboard createKeyboard();
}
4、创建实现了抽象工厂的子工厂:戴尔工厂和联想工厂
DellFactory.java
/**
* 戴尔工厂,生产戴尔鼠标和键盘
*/
public class DellFactory implements AbstractFactory {
@Override
public Mouse createMouse() {
return new DellMouse();
}
@Override
public Keyboard createKeyboard() {
return new DellKeyboard();
}
}
LenovoFactory.java
/**
* 联想工厂,生产联想鼠标和键盘
*/
public class LenovoFactory implements AbstractFactory {
@Override
public Mouse createMouse() {
return new LenovoMouse();
}
@Override
public Keyboard createKeyboard() {
return new LenovoKeyboard();
}
}
5、在客户端用的时候,就可以这样用:
public class Client {
public static void main(String[] args) {
// 使用戴尔工厂
AbstractFactory af = new DellFactory();
Mouse m = af.createMouse();
Keyboard kb = af.createKeyboard();
m.click(); // 使用戴尔鼠标进行点击...
kb.type(); // 使用戴尔键盘打字...
// 更换为联想工厂
af = new LenovoFactory();
m = af.createMouse();
kb = af.createKeyboard();
m.click(); // 使用联想鼠标进行点击...
kb.type(); // 使用联想键盘打字...
}
}
优点:
缺点:
我们将AbstractFactory、DellFactory以及LenovoFactory三个工厂类抛弃掉。取而代之的是一个简单工厂类SimpleFactory。
1、创建简单工厂
SimpleFactory.java
/**
* 简单工厂,生产鼠标和键盘
*/
public class SimpleFactory {
// 包名(此处getProperty方法为从配置文件中获取数据)
private static String packName = getProperty("packName");
// 具体需要的产品系列类型
//(此处getProperty方法为从配置文件中获取数据)
private static String type = getProperty("type");
/**
* 创建需要的鼠标对象
* @return
* @throws Exception
*/
public static Mouse createMouse() throws Exception {
String className = packName + "." + type + "Mouse";
return (Mouse)Class.forName(className).newInstance();
}
/**
* 创建需要的键盘对象
* @return
* @throws Exception
*/
public static Keyboard createKeyboard() throws Exception{
String className = packName + "." + type + "Keyboard";
return (Keyboard)Class.forName(className).newInstance();
}
}
2、配置文件中
packName=com.abstractfactory.example type=Dell
3、在客户端用的时候,就可以这样用:
public class Client {
public static void main(String[] args) throws Exception {
Mouse m = SimpleFactory.createMouse();
Keyboard kb = SimpleFactory.createKeyboard();
m.click(); // 使用戴尔鼠标进行点击...
kb.type(); // 使用戴尔键盘打字...
}
}
这样,如果我们需要更换产品系列,就可以不用修改和编译代码,直接修改配置文件就可以了。