Java设计模式-简单工厂模式

简单工厂模式并不属于 GoF 23 个经典设计模式,但通常用它作为学习其它工厂模式的基础。

简单工厂模式定义

定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态方法,所以简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。
当需要某种类实例的时候只需要传入一个正确的参数,就可以获取你想要的对象,而无需知道其创建细节。简单工厂模式的核心是工厂类的设计。

简单工厂模式结构

1、Factory(工厂角色):工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。在工厂类中提供了静态的工厂方法,它的返回类型为抽象产品类型。

2、Product(抽象产品角色):它是工厂类所创建的所有对象的父类,封装了各种产品对象的共有方法。

3、ConcreteProduct(具体产品角色):它是简单工厂模式的目标,所有被创建的对象都是这个角色的某个类的实例。每个具体产品角色都继承了抽象产品角色,需要实现抽象产品中声明的抽象方法。

简单工厂模式示例

设计简单工厂模式的步骤如下:
第一步:声明抽象产品角色,可以为抽象类,可以为接口

/**
 * Author: YiFan
 * Date: 2018/12/7 12:38
 * Description: 抽象产品角色-汽车类
 */
public abstract class Car {

    // 抽象方法-描述汽车品牌
    public abstract void desc();
}

第二步:声明具体产品角色,继承抽象产品角色,实现父类中的抽象方法

/**
 * Author: YiFan
 * Date: 2018/12/7 12:38
 * Description: 具体产品角色-宝马汽车类
 */
public class BMWCar extends Car {

    @Override
    public void desc() {
        System.out.println("宝马汽车");
    }
}

/**
 * Author: YiFan
 * Date: 2018/12/7 12:39
 * Description: 具体产品角色-奥迪汽车类
 */
public class AuDiCar extends Car {

    @Override
    public void desc() {
        System.out.println("奥迪汽车");
    }
}

第三步:声明工厂角色,SimpleCarFactory 为工厂类,提供一个静态工厂方法供外界调用,根据传入的参数创建不同的产品对象

/**
 * Author: YiFan
 * Date: 2018/12/7 12:40
 * Description: 工厂类
 */
public class SimpleCarFactory {

    /**
     * 静态方法-根据传入的参数返回不同类实例
     * @param type 传入的汽车品牌
     * @return Car对象实例
     */
    public static Car createCar(String type) {
        // 如果传入的是"BMW",则返回BMWCar类实例
        if ("BMW".equals(type)) { 
            return new BMWCar();
        // 如果传入的是"AuDi",则返回AuDiCar类实例
        } else if ("AuDi".equals(type)) {
            return new AuDiCar();
        } else {
            System.out.println("无法识别的类型");
            return null;
        }
    }
}

第四步:设计客户端,通过调用工厂类中的静态工厂方法获取相应的产品对象

/**
 * Author: YiFan
 * Date: 2018/12/7 12:41
 * Description: 客户端
 */
public class Client {

    public static void main(String[] args) {

        Car car;
        car = SimpleCarFactory.createCar("BMW");
        car.desc();
    }
}

执行结果:

宝马汽车

四个步骤:抽象产品角色->具体产品角色->工厂角色->客户端

简单工厂模式简化

有时候,为了简化简单工厂模式,可以将抽象产品角色和工厂角色结合,将静态工厂方法移至抽象产品角色中。在以上示例中,SimpleCarFactory 工厂角色与 Car 抽象产品角色结合,代码如下:

public abstract class Car {

    // 抽象方法-所有子类的共同方法
    public abstract void desc();
    
    // 静态工厂方法
    public static Car createCar(String type) {
        if ("BMW".equals(type)) {
            return new BMWCar();
        } else if ("AuDi".equals(type)) {
            return new AuDiCar();
        } else {
            System.out.println("无法识别的类型");
            return null;
        }
    }
}

简单工厂模式总结

简单工厂模式提供了专门的工厂类用于创建对象,将对象的创建和对象的使用分离开,它作为一种最简单的工厂模式在软件开发中得到了较为广泛的应用。

主要优点

1、工厂类包含必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的职责,而仅仅“消费”产品,简单工厂模式实现了对象创建和使用的分离。

2、客户的那无需知道所创建的具体产品类的类名,只需知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以在一定程度减少使用者的记忆量。

主要缺点

1、由于工厂类集中了所有产品的创建逻辑,职责过重,一旦无法正常工作则会导致整个系统受到影响。

2、使用简单工厂模式势必会增加系统中类的个数(引入新的工厂类),增加了系统的复杂度和理解难度。

3、系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,如果产品类型很多,则会导致工厂类逻辑过于复杂,不利于系统的扩展和维护。

适用场景

1、工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太过于复杂。

2、客户端只知道传入工厂类的参数,对于如何创建对象并不关心。

简单工厂模式练习

使用简单工厂模式设计一个可以创建不同几何形状(如圆形、方形和三角形等)的绘图工具,每个几何图形都具有绘制 draw() 和擦除 erase() 两个方法,要求在绘制不支持的几何图形时,提示一个 UnSupportedShapeException

设计结构图如下:
简单工厂模式练习

设计思路如下:
第一步:声明抽象产品角色

/**
 * Author: YiFan
 * Date: 2018/12/10 19:22
 * Description: 抽象产品角色
 */
public abstract class Shape {

    public abstract void draw();

    public abstract void erase();
}

第二步:声明具体产品角色

/**
 * Author: YiFan
 * Date: 2018/12/10 19:23
 * Description: 具体产品角色
 */
public class Round extends Shape {

    @Override
    public void draw() {
        System.out.println("绘制圆形");
    }

    @Override
    public void erase() {
        System.out.println("擦除圆形");
    }
}

/**
 * Author: YiFan
 * Date: 2018/12/10 19:25
 * Description: 具体产品角色
 */
public class Square extends Shape {

    @Override
    public void draw() {
        System.out.println("绘制方形");
    }

    @Override
    public void erase() {
        System.out.println("擦除方形");
    }
}

/**
 * Author: YiFan
 * Date: 2018/12/10 19:26
 * Description: 具体产品角色
 */
public class Triangle extends Shape {

    @Override
    public void draw() {
        System.out.println("绘制三角形");
    }

    @Override
    public void erase() {
        System.out.println("擦除三角形");
    }
}

第三步:声明工厂角色

/**
 * Author: YiFan
 * Date: 2018/12/10 19:27
 * Description: 工厂角色
 */
public class ShapeFactory {

    // 声明创建形状的静态工厂方法
     public static Shape createShape(String type)
             throws UnSupportedShapeException {
         Shape shape;
         if ("圆形".equals(type)) {
             shape = new Round();
         } else if ("方形".equals(type)) {
             shape = new Square();
         } else if ("三角形".equals(type)) {
             shape = new Triangle();
         } else {
             throw new UnSupportedShapeException("UnSupportedShapeException");
         }
         return shape;
     }
}

/**
 * Author: YiFan
 * Date: 2018/12/10 19:43
 * Description: 自定义异常
 */
public class UnSupportedShapeException extends Exception {

    public UnSupportedShapeException(String message) {
        super(message);
    }
}

第四步:设计客户端

/**
 * Author: YiFan
 * Date: 2018/12/10 19:34
 * Description: 客户端
 */
public class DrawingTool {

    public static void main(String[] args) {
        Shape s1, s2, s3, s4;
        try {
            s1 = ShapeFactory.createShape("圆形");
            s2 = ShapeFactory.createShape("方形");
            s3 = ShapeFactory.createShape("三角形");
            // s4 = ShapeFactory.createShape("六边形");
            s1.draw();
            s1.erase();
            s2.draw();
            s2.erase();
            s3.draw();
            s3.erase();
            // s4.draw();
            // s4.erase();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

执行结果为:

绘制圆形
擦除圆形
绘制方形
擦除方形
绘制三角形
擦除三角形

去掉其中的三处注释后,执行结果为:

UnSupportedShapeException
posted @ 2018-12-18 13:46  扇影无风  阅读(1376)  评论(0编辑  收藏  举报