• 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
    
  • 相关阅读:
    安装lamp服务器
    Linux ssh登录命令
    一些替代Xshell的软件推荐
    字符串输入的几种方式
    Java数据库操作的一些注意
    模拟堆
    web安全基础第一天
    情报搜集
    kali中的postgres怎么连接
    LeetCode:Validate Binary Search Tree
  • 原文地址:https://www.cnblogs.com/shanyingwufeng/p/10136640.html
Copyright © 2020-2023  润新知