设计模式之工厂模式

工厂模式主要是为创建对象提供了接口。工厂模式按照《Java与模式》中的提法分为三类:

  • 简单工厂模式(Simple Factory)
  • 工厂方法模式(Factory Method)
  • 抽象工厂模式(Abstract Factory)

简单工厂

// 抽象类(车)
abstract class Car {  
    public abstract void drive();  
}  

// 实现类  
class Benz extends Car {   
    public void drive() {  
        // ...
    }  
}  
class Bmw extends Car {  
    public void drive() {  
        // ...
    }  
}  

// 简单工厂  
class CarFactory {  
    public static Car createCar(String car) {  
        Car c = null;  
        if("Benz".equalsIgnoreCase(car))  
            c = new Benz();  
        else if("Bmw".equalsIgnoreCase(car))  
            c = new Bmw();  
        return c;  
    }  
}  

// 调用方
public class Client {  

    public static void main(String[] args) throws IOException {  
        // 根据 "benz" 创建实例,进行消费
        Car car = CarFactory.createCar("benz");  
        car.drive();  
    }  
}

简单工厂模式有什么好处?

首先,客户端免除了直接创建实例,而仅仅负责“消费”实例

其次,新增加一个实现类时,只要满足抽象(继承抽象接口),客户端都可以消费。

从开闭原则来分析,每增加一种实现,都要在工厂类方法中增加相应的逻辑,违背开闭原则。

简单工厂模式适用于业务简单的情况下或者具体实现类很少增加的情况。而对于复杂的业务环境可能不太适应了。

工厂方法

// 抽象类  
abstract class Car {   
    public abstract void drive();  
}  

// 实现类
class Benz extends Car {  
    public void drive() {  
        // ...
    }  
}  
class Bmw extends Car{  
    public void drive(){  
        // ...
    }  
} 

// 抽象工厂  
abstract class CarFactory {  
    public abstract Car createCar(String car);  
}  

// 工厂实现(每个工厂实现负责一个具体产品)
class BenzCarFactory extends CarFactory {  
    public Car createCar(String car) {  
        return new Benz();  
    } 
}  
class BmwCarFactory extends CarFactory {  
    public Car createCar(String car) {  
        return new Bmw();  
    }  
}  

// 调用方
public class Client {  

    public static void main(String[] args) throws Exception {  
        // 调用对应的工厂实现,创建实例,进行消费
        CarFactory factory = new BenzCarFactory();  
        Car car = factory.createCar("benz");   
        car.drive();  
    }  
} 

相比于简单工厂,工厂方法当有新的实现类产生时,只需要实现对应的工厂给调用方调用,不必修改已有的代码,是符合开闭原则的。

如果不使用工厂模式,也许代码会减少很多,不需要使用多态。但是在可维护性上,可扩展性上是非常差的。工厂模式可以提高扩展性和维护性。

抽象工厂

将工厂根据实例的复杂程度,再次抽象出一层。

// 不同抽象产品和多种的实现类
abstract class BenzCar {  
    public abstract void drive();  
} 
// 实现类
class BenzSportCar extends BenzCar {  
    public void drive() {  
        // ...
    }  
}  
class BenzBusinessCar extends BenzCar {  
    public void drive() {  
        // ...
    }  
}  

abstract class BmwCar {  
    public abstract void drive();  
}  
class BmwSportCar extends BmwCar {  
    public void drive() {  
        // ...
    }  
}  
class BmwBusinessCar extends BmwCar {  
    public void drive() {  
        // ...
    }  
}  

abstract class AudiCar{  
    public abstract void drive();  
}  
class AudiSportCar extends AudiCar {  
    public void drive(){  
        // ...
    }  
}  

// 抽象工厂  
abstract class CarFactory {  
    public abstract BenzCar createBenzCar(String car);  

    public abstract BmwCar createBmwCar(String car);  

    public abstract AudiCar createAudiCar(String car);  
}  

// 工厂实现
class SportCarFactory extends CarFactory {  
    public BenzCar createBenzCar(String car) {  
        return new BenzSportCar();  
    }  
    public BmwCar createBmwCar(String car) {  
        return new BmwSportCar();  
    }  
    public AudiCar createAudiCar(String car) {  
        return new AudiSportCar();  
    }  
}  
class BusinessCarDriver extends CarFactory {  
    public BenzCar createBenzCar(String car) {  
        return new BenzBusinessCar();  
    }  
    public BmwCar createBmwCar(String car) {  
        return new BmwBusinessCar();  
    }  
    public AudiCar createAudiCar(String car) {  
        return new AudiBusinessCar();  
    }  
} 

// 调用方
public class Client {  

    public static void main(String[] args) throws Exception {  
        // 调用对应的工厂实现,创建实例,进行消费
        CarFactory factory = new BusinessCarDriver();  
        AudiCar car = factory.createAudiCar("audi");  
        car.drive();  
    }  
} 

抽象工厂模式一般用于生产的实例具有多层级的场景下。

抽象工厂模式的缺点:如果需要增加新的抽象序列(新的抽象类+实现类),要新增多个实现类和工厂类,可以利用反射改进:

/** 
 * 简单工厂通过反射改进抽象工厂及其子工厂 
 */  
class CarFactory {  
    public static BenzCar createBenzCar(String car) {  
        return (BenzCar) Class.forName(car).newInstance();  
    }  

    public static BmwCar createBmwCar(String car) throws Exception {  
        return (BmwCar) Class.forName(car).newInstance();  
    }  

    public static AudiCar createAudiCar(String car) throws Exception {  
        return (AudiCar) Class.forName(car).newInstance();  
    }  
}  

// 调用方
public class Client {  

    public static void main(String[] args) throws Exception {  
        AudiCar car = CarFactory.createAudiCar("xxx.xxxx.AudiSportCar");  
        car.drive();  
    }  
}

Add a Comment

电子邮件地址不会被公开。 必填项已用*标注

1 × 3 =