MENU

《Java设计模式及实践》第二章读书笔记 工厂模式

May 15, 2022 • 《Java设计模式及实践》

工厂模式

优点:

  1. 一个调用者想创建一个对象,只要知道其名称就可以了。
  2. 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
  3. 屏蔽产品的具体实现,调用者只关心产品的接口。

1. 简单工厂模式

静态工厂模式

public class StaticFactory {
    public enum VehicleType {
        Car, Bike, Truck
    }
    public static Vehicle create(VehicleType type) {
        if (type.equals(VehicleType.Car))
            return new Car();
        else if (type.equals(VehicleType.Bike))
            return new Bike();
        else if (type.equals(VehicleType.Truck))
            return new Truck();
        else
            return null;
    }
}

工厂类逻辑简单,只负责产品类的实例化,符合单一职责原则,用户只需要调用产品类的接口,减少了耦合,符合依赖倒置原则,但是当增加一个新的产品时,就需要对工厂类进行修改,这样就打破了开闭原则。

以下两种就是改进过的工厂模式。

使用反射机制进行类注册的简单工厂模式

public class ReflectFactory {
    private Map<String, Class> registeredProducts = new HashMap<>();

    public void registerVehicle(String vehicleId, Class vehicleClass){
        registeredProducts.put(vehicleId, vehicleClass);
    }
    
    public Vehicle create(String type) throws IllegalAccessException, InstantiationException {
        Class productClass = registeredProducts.get(type);
        return (Vehicle) productClass.newInstance();
    }
    
    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        ReflectFactory reflectFactory = new ReflectFactory();
        reflectFactory.registerVehicle("car", Car.class);
        reflectFactory.registerVehicle("bike", Bike.class);
        reflectFactory.registerVehicle("truck", Truck.class);

        Vehicle vehicle = reflectFactory.create("car");
    }
}

但是某些情况下反射机制并不适用,比如当反射机制需要权限时或者对性能要求较高时。

使用newInstance方法进行类注册的简单工厂模式

首先在产品父类中增加一个抽象方法newInstance()

public abstract class Vehicle {
    public abstract Vehicle newInstance();
}

子类中实现这个方法

public class Bike extends Vehicle {
    @Override
    public Vehicle newInstance() {
        return new Bike();
    }
}

工程类

public class ReflectInstanceFactory {
    private Map<String, Vehicle> registeredProducts = new HashMap<>();

    public void registerVehicle(String vehicleId, Vehicle vehicle) {
        registeredProducts.put(vehicleId, vehicle);
    }

    public Vehicle create(String type) {
        return registeredProducts.get(type).newInstance();
    }

    public static void main(String[] args) {
        ReflectInstanceFactory reflectFactory = new ReflectInstanceFactory();
        reflectFactory.registerVehicle("car", new Car());
        reflectFactory.registerVehicle("bike", new Bike());
        reflectFactory.registerVehicle("truck", new Truck());

        Vehicle vehicle = reflectFactory.create("car");
    }
}

2. 工厂方法模式

工厂方法模式就是在静态工厂模式上的改进,工程类被抽象化,用于实例化特定产品类的代码被转移到实现抽象方法的子类中。这样不需要修改就可以扩展工程类。

interface People {
    void say();
}

class Man implements People{
    @Override
    public void say() {
        System.out.println("Man");
    }
}

class Woman implements People{
    @Override
    public void say() {
        System.out.println("Woman");
    }
}

abstract class PeopleFactory{
    public abstract People create();
}

class ManFactory extends PeopleFactory{
    @Override
    public People create() {
        return new Man();
    }
}

class WomanFactory extends PeopleFactory{
    @Override
    public People create() {
        return new Woman();
    }
}

public class FactoryMethod {
    public static void main(String[] args) {
        PeopleFactory manFactory = new ManFactory();
        People people = manFactory.create();
        people.say();
    }
}

3. 抽象工厂模式

抽象工厂模式时工厂方法模式的扩展版本,它不再是创建单一类型的对象,而是创建一系列相关联的对象。

工厂方法类中只有一个抽象方法,在不同的具体工厂类中分别实现抽象产品的实例化,而抽象工厂类中,每个抽象产品都有一个实例化方法。

如果我们采用抽象工厂模式并将其用于包含单个对象的簇,那么就成为了工厂方法模式,所以说工厂方法模式只是抽象工厂模式的一种特例。

抽象工厂模式类的组成
  • AbstractFactory(抽象工厂类):抽象类,用于声明创建不同类型产品的方法,它针对不同的抽象产品类都有对应的创建方法。
  • ConcreteFactory(具体工程类):具体类,用于实现抽象工厂基类中声明的方法,针对每个系列的产品都有一个对应的具体工厂类。
  • AbstractProduct(抽象产品类):对像所需的基本接口或类。一簇相关的产品类由来自不同层级的相似产品类组成。比如,ProductA1和ProductA2来自第一个类簇,有ConcreteFactory1实例化,ProductB1和ProductB2来自第二个类簇,有ConcreteFactory2实例化.
UML图

abstractfactory_pattern_uml_diagram

//Shape.java   抽象产品类
public interface Shape {
    void draw();
}
//Color.java   抽象产品类
public interface Color {
    void fill();
}
//...各具体产品类
//AbstractFactory.java   抽象工厂类
public abstract class AbstractFactory {
    public abstract Color getColor(String color);
    public abstract Shape getShape(String shape);

    public static void main(String[] args) {

    }
}
//ShapeFactory.java  具体工厂类
public class ShapeFactory extends AbstractFactory {
    @Override
    public Color getColor(String color) {
        return null;
    }

    @Override
    public Shape getShape(String shape) {
        if (shape == null)
            return null;

        if (shape.equalsIgnoreCase("CIRCLE"))
            return new Circle();
        else if (shape.equalsIgnoreCase("RECTANGLE"))
            return new Rectangle();

        return null;
    }
}
//ColorFactory.java  具体工厂类
public class ColorFactory extends AbstractFactory {
    @Override
    public Color getColor(String color) {
        if (color == null)
            return null;

        if (color.equalsIgnoreCase("RED"))
            return new Red();
        else if (color.equalsIgnoreCase("GREEN"))
            return new Green();

        return null;
    }

    @Override
    public Shape getShape(String shape) {
        return null;
    }
}
//FactoryProducer.java
public class FactoryProducer {
    public static AbstractFactory getFactory(String choice){
        if(choice == null)
            return null;
        if(choice.equalsIgnoreCase("SHAPE")){
            return new ShapeFactory();
        } else if(choice.equalsIgnoreCase("COLOR")){
            return new ColorFactory();
        }
        return null;
    }
}

Git 代码

Sundae97/Design-Patterns-Java