美文网首页Java
Java 设计模式——工厂模式

Java 设计模式——工厂模式

作者: 斌林诚上 | 来源:发表于2018-11-17 21:07 被阅读10次
    image

    前言

    最近在复习java设计模式中的工厂模式。本来有一点小小的理解。感觉都写的不错,就是有点太零散了,最后还是决定自己手写一把,加深印象。顺便做个总结,以后复习起来也方便许多。

    一、简介

    目前从网上了解工厂模式大体分为简单工厂、工厂方法、抽象工厂等三种模式。工厂方法模式也可称为工厂模式,与抽象模式都是属于GOF23种设计模式中的一员。可以大概理解为:简单工厂进阶变成了工厂方法,然后再进阶成了抽象工厂。难度逐步增加,也越来越抽象。下面按先易到难逐个分析。

    二、简单工厂模式

    属于创建型模式,又叫做静态工厂方法模式,不属于23种GOF设计模式之一。是由一个工厂对象决定创建出哪一种产品类的实例。实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

    作用:将“类实例化的操作”与“使用对象的操作”分开,让使用者不用知道具体参数就可以实例化出所需要的“产品”类,从而避免了在客户端代码中显式指定,实现了解耦。

    主要角色
    工厂:负责实现创建所有实例的内部逻辑,并提供一个外界调用的方法,创建所需的产品对象。
    抽象产品:负责描述产品的公共接口
    具体产品:描述生产的具体产品。
    举个简单易懂的例子:
    “假设”有一台饮料机(工厂),可以调出各种口味的饮料(抽象产品),有三个按钮(参数)对应这三种饮料(具体产品)。这时候你可以根据点击按钮来选择你喜欢的饮料。

    /**
     *  @ Product.java
     *  抽象产品
     *  描述产品的公共接口
     */
    abstract  class Product {
        //产品介绍
        abstract void intro();
    }
    
    /**
     * @ AProduct.java
     * 具体产品A
     * (可以看成是一种饮料:可乐)
     */
    public class AProduct extends Product{
        @Override
        void intro() {
            System.out.println("可乐");
        }
    }
    
    /**
     * @ BProduct.java
     * @具体产品B
     * @(可以看成是一种饮料:奶茶)
     */
    public class BProduct extends Product{
        @Override
        void intro() {
            System.out.println("奶茶");
        }
    }
    
    /**
     * @ CProduct.java
     * 具体产品C
     * (可以看成是一种饮料:咖啡)
     */
    public class CProduct extends Product{
        @Override
        void intro() {
            System.out.println("咖啡");
        }
    }
    
    image.gif

    Factory.java

    /**
     * 工厂
     * 负责实现创建所有实例的内部逻辑,并提供一个外界调用的方法,创建所需的产品对象。
     */
    public class Factory {
        /**
         * 供外界调用的方法
         * (可以看成是对外提供的三种按钮)
         * @param type 
         * @return 产品实例
         */
        public static Product getProduct(String type) {
            switch (type) {
                case "A":
                    return new AProduct();
                case "B":
                    return new BProduct();
                case "C":
                    return new CProduct();
                default:
                    return null;
            }
        }
    }
    
    image.gif

    测试

    public class Test {
        public static void main(String[] args) {
            //创建具体的工厂
            Factory factory = new Factory();
            //根据传入的参数生产不同的产品实例
            //(按下不同的按钮,获取饮料)
            Product A = Factory.getProduct("A");
            A.intro();
            Product B = Factory.getProduct("B");
            B.intro();
            Product C = Factory.getProduct("C");
            C.intro();
        }
    }
    
    image.gif image

    根据例子可以描述为:一个抽象产品类,可以派生出多个具体产品类。一个具体工厂类,通过往此工厂的static方法中传入不同参数,产出不同的具体产品类实例。

    优点:将创建使用工作分开,不必关心类对象如何创建,实现了解耦;
    缺点:违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂。

    三、工厂方法模式

    又称工厂模式、多态工厂模式虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。一种常用的对象创建型设计模式,此模式的核心精神是封装 类中不变的部分。

    作用:将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一个类。

    主要角色
    抽象工厂:描述具体工厂的公共接口
    具体工厂:描述具体工厂,创建产品的实例,供外界调用
    抽象产品:负责描述产品的公共接口
    具体产品:描述生产的具体产品

    举个简单易懂的例子:
    “假设”有各类的饮料机(抽象工厂),可以调出各种的饮料(抽象产品)。但是一类饮料机(具体工厂),只能生产一种饮料(具体产品)。如果你需要喝可乐,就需要买可乐饮料机。

    产品:Product.java 、ProductA.java 、ProductB.java

    /**
     * @ Product.java 
     *   抽象产品
     */
    abstract class Product {
        //产品介绍
        abstract void intro();
    }
    
    /**
     * @ ProductA.java 
     * 具体产品A
     */
    public class ProductA extends Product{
        @Override
        void intro() {
            System.out.println("饮料A");
        }
    }
    
    /**
     * @ ProductB.java 
     * 具体产品B
     */
    public class ProductB extends Product{
        @Override
        void intro() {
            System.out.println("饮料B");
        }
    }
    
    image.gif

    工厂:Factory.java、FactoryA.java 、FactoryB.java

    /**
     *  @ Factory.java
     *    抽象工厂
     */
    abstract class Factory {
        //生产产品
        abstract Product getProduct();
    }
    
    /**
     * @ FactoryA.java
     * 具体工厂A
     * 负责具体的产品A生产
     */
    public class FactoryA extends Factory{
        @Override
        Product getProduct() {
            return new ProductA();
        }
    }
    
    /**
     * @ FactoryB.java
     * @具体工厂B
     * 负责具体的产品B生产
     */
    public class FactoryB extends Factory{
        @Override
        Product getProduct() {
            return new ProductB();
        }
    }
    
    image.gif

    测试:Test.java

    public class Test {
        public static void main(String[] args) {
            //创建具体的工厂
            FactoryA factoryA = new FactoryA();
            //生产相对应的产品
            factoryA.getProduct().intro();
            FactoryB factoryB = new FactoryB();
            factoryB.getProduct().intro();
        }
    }
    
    image.gif

    根据例子可以描述为:一个抽象产品类,可以派生出多个具体产品类。一个抽象工厂类,可以派生出多个具体工厂类。每个具体工厂类只能创建一个具体产品类的实例

    优点:

    1. 符合开-闭原则:新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可
    2. 符合单一职责原则:每个具体工厂类只负责创建对应的产品

    缺点:

    1. 增加了系统的复杂度:类的个数将成对增加
    2. 增加了系统的抽象性和理解难度
    3. 一个具体工厂只能创建一种具体产品

    四、抽象工厂模式

    定义:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类;具体的工厂负责实现具体的产品实例。
    解决的问题:每个工厂只能创建一类产品(工厂方法模式)

    抽象工厂模式与工厂方法模式最大的区别:抽象工厂中每个工厂可以创建多种类的产品;而工厂方法每个工厂只能创建一类

    主要对象
    抽象工厂:描述具体工厂的公共接口
    具体工厂:描述具体工厂,创建产品的实例,供外界调用
    抽象产品族:描述抽象产品的公共接口
    抽象产品:描述具体产品的公共接口
    具体产品:具体产品

    举个简单易懂的例子:(找了个不怎么好的比喻,看不懂得可以看相关推荐链接)
    “假设”有各类的自动售卖机(抽象工厂),可以出售各类食品(抽象产品族)。
    有饮料、零食(抽象产品),比如常见的零食售卖机(具体工厂),出售矿泉水与面包(具体产品)。

    产品:Product、ProductA、ProductB、ProductAa、ProductBb

    /**
     * @ Product.java
     * 抽象产品族 (食品)
     */
    abstract class Product {
        //产品介绍
        abstract void intro();
    }
    
    /**
     * @ ProductA.java
     * 抽象产品  (饮料)
     */
    abstract class ProductA extends Product{
        @Override
        abstract void intro();
    }
    
    /**
     * @ ProductB.java
     * 抽象产品  (零食)
     */
    abstract class ProductB extends Product{
        @Override
        abstract void intro();
    }
    
    /**
     * @ ProductAa.java
     * 具体产品  (矿泉水)
     */
    public  class ProductAa extends ProductA{
        @Override
        void intro() {
            System.out.println("矿泉水");
        }
    }
    
    /**
     * @ ProductBb.java
     * 抽象产品  (面包)
     */
    public class ProductBb extends ProductB{
        @Override
        void intro() {
            System.out.println("面包");
        }
    }
    
    image.gif

    工厂:Factory.java、FactoryA.java

    /**
     * @ Factory.java
     * 抽象工厂
     */
    abstract class Factory {
        //生产饮料
        abstract Product getProductA();
        //生产零食
        abstract Product getProductB();
    }
    
    /**
     * @ FactoryA.java
     * 具体工厂A
     * 负责具体的A类产品生产
     */
    public class FactoryA extends Factory{
        @Override
        Product getProductA() {
            //生产矿泉水
            return new ProductAa();
        }
        @Override
        Product getProductB() {
            //生产面包
            return new ProductBb();
        }
    }
    
    
    image.gif

    测试:Test.java

    public class Test {
        public static void main(String[] args) {
            //创建零食售卖机(具体工厂),
            FactoryA factoryA = new FactoryA();
            //获取矿泉水与面包(具体产品)
            factoryA.getProductA().intro();
            factoryA.getProductB().intro();
        }
    }
    
    image.gif image image.gif

    根据实例可以描述为: 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类可以创建多个具体产品类的实例。.

    优点:

    1. 降低耦合
    2. 符合开-闭原则
    3. 符合单一职责原则
    4. 不使用静态工厂方法,可以形成基于继承的等级结构。

    缺点:难以扩展新种类产品

    五、总结

    角色不同:

    1. 简单工厂:具体工厂、抽象产品、具体产品
    2. 工厂方法:抽象工厂、具体工厂、抽象产品、具体产品
    3. 抽象工厂:抽象工厂、具体工厂、抽象产品族、抽象产品、具体产品

    定义:

    1. 简单工厂:由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(继承自一个父类或接口)的实例。
    2. 工厂方法:定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象
    3. 抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类;具体的工厂负责实现具体的产品实例。

    对比:

    1. 工厂方法模式解决了简单工厂模式的“开放 - 关闭原则
    2. 抽象工厂模式解决了工厂方法模式一个具体工厂只能创建一类产品

    六、Demo地址

    https://github.com/DayorNight/DesignPattern

    六、参考文档

    简单工厂模式

    https://www.jianshu.com/p/e55fbddc071c

    https://baike.baidu.com/item/%E7%AE%80%E5%8D%95%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/8801727

    工厂方法模式

    https://www.jianshu.com/p/d0c444275827

    抽象工厂模式

    https://www.jianshu.com/p/7deb64f902db

    七、内容推荐

    CSDN: https://blog.csdn.net/cs_lwb/article/details/83999073

    上一篇《JAVA 设计模式——单例模式》

    如果你觉得我写的不错或者对您有所帮助的话。不妨顶一个(点个赞呗),也方便以后复习

    您的每个举动都是对我莫大的支持

    谢谢了!!!

    image

    相关文章

      网友评论

        本文标题:Java 设计模式——工厂模式

        本文链接:https://www.haomeiwen.com/subject/xqxlfqtx.html