工厂模式

工厂模式作用

在工厂模式中,在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。

工厂模式可以分为三类:

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

简单工厂其实不是一个标准的的设计模式。简单工厂模式可以看为工厂方法模式的一种特例。

优点:

  • 一个调用者想创建一个对象,只要知道其名称就可以了。
  • 屏蔽产品的具体实现,调用者只关心产品的接口。

简单工厂模式

  • 创建一个抽象类产品Shape接口和实现Shape接口的实体类(具体产品)。
  • 定义工厂类ShapeFactory
  • Client使用ShapeFactory来获取Shape对象。它将向ShapeFactory传递信息(CIRCLE、RECTANGLE、SQUARE),以便获取它所需对象的类型。

简单工厂模式实例

创建接口

package creational.simple_factory_method;

public interface Shape {
    void draw();
}

创建实现接口的实体类

Rectangle.java

package creational.simple_factory_method;

public class Rectangle implements Shape{
    @Override
    public void draw() {
        System.out.println("Inside Rectangle::draw() method.");
    }
}

Square.java

package creational.simple_factory_method;

public class Square implements Shape{
    @Override
    public void draw() {
        System.out.println("Inside Square::draw() method.");
    }
}

创建工厂

使用了反射

package creational.simple_factory_method;

public class ShapeFactory {
    /**
     * 注意,这里需要是static
     */
    public static Shape getShape(String shapeType) {
        Shape shape = null;
        try {
            shape = (Shape) Class.forName(shapeType).newInstance();
        } catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return shape;
    }
}

客户调用

package creational.simple_factory_method;

public class Client {
    public static void main(String[] args) {
        Shape shape = ShapeFactory.getShape("creational.simple_factory_method.Square");
        if (shape != null) {
            shape.draw();  // Inside Square::draw() method.
        }
    }
}

工厂方法模式

工厂方法模式实例

创建抽象产品和具体产品

创建抽象产品:

package creational.factory_method.product;

/**
 * 通用产品接口:产品接口中将声明所有具体产品都必须实现的操作。
 * @author chenzufeng
 */
public interface Animal {
    void show();
}

具体产品:

package creational.factory_method.product;

public class Horse implements Animal {
    @Override
    public void show() {
        System.out.println("展示刚出生的小马!");
    }
}
package creational.factory_method.product;

public class Cattle implements Animal{
    @Override
    public void show() {
        System.out.println("展示刚出生的小牛!");
    }
}

创建抽象工厂和具体工厂

创建抽象工厂:

package creational.factory_method.factory;

import creational.factory_method.product.Animal;

/**
 * 基础创建者
 * [创建者类]声明的工厂方法必须返回一个产品类的对象。[创建者的子类]通常会提供该方法的实现。
 * Base factory class.
 * Note that "factory" is merely a role for the class.
 * It should have some core business logic which needs different products to be created.
 * @author chenzufeng
 */
public abstract class AnimalFactory {
    /**
     * 具体创建者需要提供一些工厂方法的默认实现
     * Subclasses will override this method in order to create specific button objects.
     * @return Animal
     */
    public abstract Animal createAnimal();

    /**
     * Creator's primary responsibility isn't creating products.
     * It usually contains some [core business logic] that relies on product objects returned by the factory method.
     * Subclasses can indirectly change that business logic by [overriding the factory method] and
     * returning a different type of product from it.
     */
    public void renderAnimal() {
        Animal animal = createAnimal();
        animal.show();
    }
}

创建具体工厂:

package creational.factory_method.factory;

import creational.factory_method.product.Animal;
import creational.factory_method.product.Horse;

public class HorseFactory extends AnimalFactory{
    @Override
    public Animal createAnimal() {
        return new Horse();
    }
}
package creational.factory_method.factory;

import creational.factory_method.product.Animal;
import creational.factory_method.product.Cattle;

public class CattleFactory extends AnimalFactory{
    @Override
    public Animal createAnimal() {
        return new Cattle();
    }
}

客户端

package creational.factory_method;

import creational.factory_method.factory.AnimalFactory;
import creational.factory_method.factory.CattleFactory;
import creational.factory_method.factory.HorseFactory;

public class Client {
    private static AnimalFactory animalFactory;

    public static void main(String[] args) {
        configure("Horse");
        runBusinessLogic();
    }

    /**
     * The concrete factory is usually chosen depending on configuration.
     */
    static void configure(String animalType) {
        if (animalType.equalsIgnoreCase("Horse")) {
            animalFactory = new HorseFactory();
        } else if (animalType.equalsIgnoreCase("Cattle")) {
            animalFactory = new CattleFactory();
        }
    }

    /**
     * All of the client code should work with factories and products through abstract interfaces.
     * This way it does not care which factory it works with and what kind of product it returns.
     */
    static void runBusinessLogic() {
        animalFactory.renderAnimal();
    }
}

工厂方法模式优缺点

优缺点

工厂方法模式的主要优点有:

  • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程
  • 在系统增加新的产品时只需要添加具体产品类对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则。
  • 解耦合
    • 耦合:代码间的强关联,一方的改变会影响到另一方,不利于代码维护(把接口的实现类,硬编码在程序中)

其缺点是

  • 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
  • 抽象产品只能生产产品的一种类型

抽象工厂模式

工厂方法模式中考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机。但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如农场里既养动物又种植物,电器厂既生产电视机又生产洗衣机或空调等。

抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级(种类)的产品,而抽象工厂模式可生产多个等级(种类)的产品

抽象工厂模式结构

抽象工厂模式实例

抽象产品与具体产品

抽象产品:椅子和沙发

package creational.abstract_factory_method.products.chair;

/**
 * 系列产品中的特定产品必须有一个基础接口。所有产品变体都必须实现这个接口。
 * Abstract Factory assumes that you have several families of products,
 * structured into separate class hierarchies (Chair/Sofa).
 * All products of the same family have the common interface.
 *
 * This is the common interface for chairs family.
 * @author chenzufeng
 */
public interface Chair {
    void sitOn();
}
package creational.abstract_factory_method.products.sofa;

/**
 * This is the common interface for sofa family.
 * @author chenzufeng
 */
public interface Sofa {
    void sitOn();
}

具体产品:维多利亚和现代风格的椅子和沙发

维多利亚风格的椅子

package creational.abstract_factory_method.products.chair;

/**
 * 具体产品由相应的具体工厂创建。
 * All products families have the same varieties (Victorian/Modern).
 * This is a Victorian variant of a chair. 维多利亚风格的椅子
 * @author chenzufeng
 */
public class VictorianChair implements Chair {
    @Override
    public void sitOn() {
        System.out.println("坐在维多利亚风格的椅子上!");
    }
}

现代风格的椅子

package creational.abstract_factory_method.products.chair;

/**
 * 具体产品由相应的具体工厂创建。
 * All products families have the same varieties (Victorian/Modern).
 * This is a Modern variant of a chair. 现代风格的椅子
 * @author chenzufeng
 */
public class ModernChair implements Chair {
    @Override
    public void sitOn() {
        System.out.println("坐在现代风格的椅子上!");
    }
}

维多利亚风格的沙发

package creational.abstract_factory_method.products.sofa;

/**
 * 具体产品由相应的具体工厂创建。
 * All products families have the same varieties (Victorian/Modern).
 * This is a Victorian variant of a sofa. 维多利亚风格的沙发
 * @author chenzufeng
 */
public class VictorianSofa implements Sofa {
    @Override
    public void sitOn() {
        System.out.println("坐在维多利亚风格的沙发上!");
    }
}

现代风格的沙发

package creational.abstract_factory_method.products.sofa;

/**
 * 具体产品由相应的具体工厂创建。
 * All products families have the same varieties (Victorian/Modern).
 * This is a Modern variant of a chair. 现代风格的沙发
 * @author chenzufeng
 */
public class ModernSofa implements Sofa {
    @Override
    public void sitOn() {
        System.out.println("坐在现代风格的沙发上!");
    }
}

抽象工厂与具体工厂

抽象工厂

package creational.abstract_factory_method.factories;

import creational.abstract_factory_method.products.chair.Chair;
import creational.abstract_factory_method.products.sofa.Sofa;

/**
 * 抽象工厂接口声明了一组能返回不同抽象产品的方法。
 * 这些产品属于[同一个系列]且在高层主题或概念上具有相关性。
 * 同系列的产品通常能相互搭配使用:【现代风格的沙发和椅子】。
 * 系列产品可有多个变体(现代风格和维多利亚风格),但不同变体的产品不能搭配使用。
 * Abstract factory knows about all (abstract) product types.
 * @author chenzufeng
 */
public interface FurnitureFactory {
    /**
     * 创建不同风格的椅子
     * @return Chair
     */
    Chair createChair();

    /**
     * 创建不同风格的沙发
     * @return Sofa
     */
    Sofa createSofa();
}

具体工厂

维多利亚家具厂:

package creational.abstract_factory_method.factories;

import creational.abstract_factory_method.products.chair.Chair;
import creational.abstract_factory_method.products.chair.VictorianChair;
import creational.abstract_factory_method.products.sofa.Sofa;
import creational.abstract_factory_method.products.sofa.VictorianSofa;

/**
 * 维多利亚家具厂:生产维多利亚风格的椅子和沙发
 * @author chenzufeng
 */
public class VictorianFurnitureFactory implements FurnitureFactory {
    @Override
    public Chair createChair() {
        return new VictorianChair();
    }

    @Override
    public Sofa createSofa() {
        return new VictorianSofa();
    }
}

现代风格家具厂:

package creational.abstract_factory_method.factories;

import creational.abstract_factory_method.products.chair.Chair;
import creational.abstract_factory_method.products.chair.ModernChair;
import creational.abstract_factory_method.products.sofa.ModernSofa;
import creational.abstract_factory_method.products.sofa.Sofa;

/**
 * 现代风格家具厂:生产现代风格椅子和沙发
 * @author chenzufeng
 */
public class ModernFurnitureFactory implements FurnitureFactory {
    @Override
    public Chair createChair() {
        return new ModernChair();
    }

    @Override
    public Sofa createSofa() {
        return new ModernSofa();
    }
}

客户端

客户端应用:

package creational.abstract_factory_method.app;

import creational.abstract_factory_method.factories.FurnitureFactory;
import creational.abstract_factory_method.products.chair.Chair;
import creational.abstract_factory_method.products.sofa.Sofa;

/**
 * 客户端应用代码
 * @author chenzufeng
 */
public class Application {
    private Chair chair;
    private Sofa sofa;

    public Application(FurnitureFactory furnitureFactory) {
        chair = furnitureFactory.createChair();
        sofa = furnitureFactory.createSofa();
    }

    public void sitOn() {
        chair.sitOn();
        sofa.sitOn();
    }
}

客户挑选统一风格的家具:

package creational.abstract_factory_method.app;

import creational.abstract_factory_method.factories.FurnitureFactory;
import creational.abstract_factory_method.factories.ModernFurnitureFactory;
import creational.abstract_factory_method.factories.VictorianFurnitureFactory;

/**
 * 客户使用app挑选统一风格的家具
 * @author chenzufeng
 */
public class Client {
    public static void main(String[] args) {
        Application application = configure("Modern");
        application.sitOn();
    }

    private static Application configure(String styleType) {
        Application application;
        FurnitureFactory furnitureFactory;

        if (styleType.equalsIgnoreCase("Modern")) {
            furnitureFactory = new ModernFurnitureFactory();
        } else if (styleType.equalsIgnoreCase("Victorian")) {
            furnitureFactory = new VictorianFurnitureFactory();
        } else {
            furnitureFactory = null;
        }

        application = new Application(furnitureFactory);
        return application;
    }
}

输出结果:

坐在现代风格的椅子上!
坐在现代风格的沙发上!
posted @ 2021-03-11 12:08  chenzufeng  阅读(97)  评论(0)    收藏  举报