工厂模式
工厂模式(Factory Pattern)是Java中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
介绍
意图:
定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:接口选择问题。
应用实例:
- 客户需要购买一辆汽车,只需要到相应的4S店购买即可,而不用去管这辆汽车是怎样生产出来的;
- Hibernate换数据库只需要换方言和驱动就可以;
- springboot修改web服务器,只需要修改配置参数即可。
优点:
- 一个调用者想创建一个对象,只要知道其名称就可以了;
- 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以;
- 屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
使用场景:
- 日志记录器:不同的日志级别可能要记录在不同的路径。
- 数据库访问,当用户不知道请求最后要访问到哪个数据库时。
- 设计一个连接服务器的框架,需要支持三种协议,“POP3”、“IMAP”、“HTTP”,可以把三个协议作为产品类,共同实现一个接口。
注意事项:
作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合工厂模式,而简单对象,特别是只需要通过new就可以完成创建的对象,无需使用工厂模式。如果使用工厂农事,就需要引入一个工厂类,会增加系统的复杂度。
实现
比如我们现在要创建一个几何图形,已知可以创建circle、rectangle、square三种图形,以下是具体实现。
FactoryPatternDemo类使用ShapeFactory来获取Shape对象。它将向ShapeFactory传递信息(circle、rectangle、square),以便获取它所需对象的类型。
工厂模式demo
以生产手机为例
- 创建手机接口
public interface Phone {
/**
* 打电话
*/
void call();
}
- 创建接口实现类
public class Huawei implements Phone {
@Override
public void call() {
System.out.println("用华为手机打电话!!!");
}
}
public class OPPO implements Phone{
@Override
public void call() {
System.out.println("用OPPO手机打电话!!!");
}
}
public class VIVO implements Phone{
@Override
public void call() {
System.out.println("用VIVO手机打电话!!!");
}
}
- 创建手机工厂
public class PhoneFactory {
public static final String HUAWEI = "HUAWEI";
public static final String OPPO = "OPPO";
public static final String VIVO = "VIVO";
public Phone createPhone(String phoneType){
if (phoneType == null || phoneType.length() == 0){
return null;
}
switch (phoneType){
case HUAWEI:
return new Huawei();
case OPPO:
return new OPPO();
case VIVO:
return new VIVO();
default:
return null;
}
}
}
- 创建测试类
public class FactoryPatternDemo {
public static void main(String[] args) {
PhoneFactory phoneFactory = new PhoneFactory();
Phone huawei = phoneFactory.createPhone(PhoneFactory.HUAWEI);
huawei.call();
Phone oppo = phoneFactory.createPhone(PhoneFactory.OPPO);
oppo.call();
Phone vivo = phoneFactory.createPhone(PhoneFactory.VIVO);
vivo.call();
}
}
- 测试结果
用华为手机打电话!!!
用OPPO手机打电话!!!
用VIVO手机打电话!!!
抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式。
介绍
意图
一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类。
主要解决
接口选择问题。
应用实例
去吃肯德基的时候,点套餐的时候有主食和饮料,不同的主食和饮料组合成不同的套餐。那么就需要一个套餐工厂来生产套餐,同时需要主食工厂来生产不同的主食,例如汉堡、米饭等,还需要饮料工厂生产不同饮品,例如可乐、果汁等。
优点
当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点
产品族扩展非常困难,要增加一系列的某一产品,既要抽象的Creator里加代码,又要在具体的实现类里加代码。
使用场景
- QQ秀换装,按照套装换装;
- 生成不同操作系统的程序。
注意事项
产品族难扩展,产品等级易扩展。
实现
现在我们要创建带颜色的几何图形,我们将创建Shape和Color接口和实现这些接口的类。下一步创建抽象工厂类AbstractFactory。接着定义工厂类ShapeFactory和ColorFactory,两个工厂都扩展了AbstractFactory。然后创建一个工厂创造器/生成器类FactoryProducer。
AbstractFactoryPatternDemo类使用FactoryProduce来获取AbstractFactory对象。它将向AbstractFactory传递形状信息Shape(circle/rectangle/square),以获取它所需要的形状对象类型。同时还向AbstractFactory传递颜色信息Color(red/green/blue),以获取它所需的颜色对象类型。
抽象工厂模式demo
沿用抽象工厂demo中的代码
- 创建手机壳接口
public interface PhoneShell {
void color();
}
- 创建手机壳实现类
public class BlackPhoneShell implements PhoneShell{
@Override
public void color() {
System.out.println("黑色手机壳!!!");
}
}
public class BluePhoneShell implements PhoneShell{
@Override
public void color() {
System.out.println("蓝色手机壳!!!");
}
}
public class RedPhoneShell implements PhoneShell{
@Override
public void color() {
System.out.println("红色手机壳!!!");
}
}
- 创建抽象工厂
public abstract class AbstractFactory {
//创建手机
public abstract Phone createPhone(String phoneType);
//创建手机壳
public abstract PhoneShell createPhoneShell(String color);
}
- 创建手机工厂
public class PhoneFactory extends AbstractFactory{
public static final String HUAWEI = "HUAWEI";
public static final String OPPO = "OPPO";
public static final String VIVO = "VIVO";
@Override
public Phone createPhone(String phoneType) {
if (phoneType == null || phoneType.length() == 0){
return null;
}
switch (phoneType){
case HUAWEI:
return new Huawei();
case OPPO:
return new OPPO();
case VIVO:
return new VIVO();
default:
return null;
}
}
@Override
public PhoneShell createPhoneShell(String color) {
return null;
}
}
- 创建手机壳工厂
public class PhoneShellFactory extends AbstractFactory{
public static final String RED = "RED";
public static final String BLUE = "BLUE";
public static final String BLACK = "BLACK";
@Override
public Phone createPhone(String phoneType) {
return null;
}
@Override
public PhoneShell createPhoneShell(String color) {
if (color == null || color.length() == 0){
return null;
}
switch (color){
case RED:
return new RedPhoneShell();
case BLUE:
return new BluePhoneShell();
case BLACK:
return new BlackPhoneShell();
default:
return null;
}
}
}
- 创建一个工厂创造器
public class FactoryProducer {
public static final String PHONE = "PHONE";
public static final String PHONE_SHELL = "PHONESHELL";
public static AbstractFactory createFactory(String factpryType){
if (PHONE.equals(factpryType)){
return new PhoneFactory();
}else if (PHONE_SHELL.equals(factpryType)){
return new PhoneShellFactory();
}
return null;
}
}
- 创建抽象工厂测试类
public class AbstractFactoryDemo {
public static void main(String[] args) {
AbstractFactory phoneFactory = FactoryProducer.createFactory(FactoryProducer.PHONE);
Phone huawei = phoneFactory.createPhone(PhoneFactory.HUAWEI);
Phone oppo = phoneFactory.createPhone(PhoneFactory.OPPO);
Phone vivo = phoneFactory.createPhone(PhoneFactory.VIVO);
huawei.call();
oppo.call();
vivo.call();
AbstractFactory phoneShellFactory = FactoryProducer.createFactory(FactoryProducer.PHONE_SHELL);
PhoneShell blackPhoneShell = phoneShellFactory.createPhoneShell(PhoneShellFactory.BLACK);
PhoneShell bluePhoneShell = phoneShellFactory.createPhoneShell(PhoneShellFactory.BLUE);
PhoneShell redPhoneShell = phoneShellFactory.createPhoneShell(PhoneShellFactory.RED);
blackPhoneShell.color();
bluePhoneShell.color();
redPhoneShell.color();
}
}
- 测试结果
用华为手机打电话!!!
用OPPO手机打电话!!!
用VIVO手机打电话!!!
黑色手机壳!!!
蓝色手机壳!!!
红色手机壳!!!