Java设计模式之工厂模式

1. 工厂模式概述

1.1 工厂模式的意义

将实例化对象的代码提取出来, 放到一个类中统一管理和维护, 达到和主项目的依赖关系的解耦。 从而提高项目的扩展和维护性。

1.2 工厂模式的分类

工厂模式可以分为三类,简单工厂模式、 工厂方法模式、 抽象工厂模式。

1.3 设计模式的依赖抽象原则

1.创建对象实例时, 不要直接 new 类, 而是把这个 new 类的动作放在一个工厂的方法中, 并返回。 有的书上说,变量不要直接持有具体类的引用。
2.不要让类继承具体类, 而是继承抽象类或者是实现 interface(接口)
3.不要覆盖基类中已经实现的方法

2. 工厂模式详解

2.1 简单工厂简介

1)简单工厂模式属于创建型模式,是工厂模式最简单的一种。 简单工厂模式是由一个工厂对象觉得创建出哪一种产品类的实例。简单工厂模式是工厂模式家族种最简单使用的模式。
2) 简单工厂模式: 定义了一个创建对象的类, 由这个类来封装实例化对象的行为(代码)
3) 在软件开发中, 当我们会用到大量的创建某种、 某类或者某批对象时, 就会使用到工厂模式.

简单工厂就是通过参数实现创建不同的对象。
优点
(1)简单工厂包含必要的判断逻辑,简单工厂实现了对象的创建和使用的分离。
(2)客户端无需知道所创建的具体产品类的类名,只需要具体产品类对应的参数即可!
(3)在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性
缺点
(1)工厂类的职责过重,从类图中可以看出简单工厂中的逻辑判断语句,它一旦有问题,整个系统都要出问题
(2)在添加新的类的时候,那么系统中的简单工厂类就要修改,违反了开放——封闭原则!这样及其不利于系统的扩展和维护!
(3)简单工厂的静态方法,使得工厂角色无法形成基于继承的等级结构!

2.2 工厂模式简介

1) 工厂方法模式设计方案: 将披萨项目的实例化功能抽象成抽象方法, 在不同的口味点餐子类中具体实现。
2) 工厂方法模式: 定义了一个创建对象的抽象方法, 由子类决定要实例化的类。 工厂方法模式将对象的实例
化推迟到子类。

工厂模式
通过工厂A创建产品A,工厂B创建产品B,工厂C创建产品C

优点:
(1)不同的工厂创建不同的产品,隐藏了细节。
(2)在增加修改新的运算类的时候不用修改代码,只需要增加对应的工厂就好,完全符合开放——封闭性原则!
(3)创建对象的细节完全封装在具体的工厂内部,而且有了抽象的工厂类,所有的具体工厂都继承了自己的父类!完美的体现了多态性!

缺点:
(1)在增加新的产品(对应UML图的算法)时,也必须增加新的工厂类,会带来额外的开销
(2)抽象层的加入使得理解程度加大


2.3 抽象工厂简介

抽象工厂
抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类,
抽象工厂模式较好的实现了“开放-封闭”原则,是三个模式中较为抽象,并具一般性的模式。
我们在使用中要注意使用抽象工厂模式的条件。

1) 抽象工厂模式: 定义了一个 interface 用于创建相关或有依赖关系的对象簇, 而无需指明具体的类
2) 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。
3) 从设计层面看, 抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。
4) 将工厂抽象成两层, AbsFactory(抽象工厂) 和 具体实现的工厂子类。 程序员可以根据创建对象类型使用对应
的工厂子类。 这样将单个的简单工厂类变成了工厂簇, 更利于代码的维护和扩展。

3. 工厂模式实现

3.1 简单工厂实现

/**
 * 产品接口类
 * 声明类所需继承的共同接口,也可以是抽象类
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public interface Product {
}
/**
 * 产品A
 * ProductA 实现 Product接口
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public class ProductA implements Product {
    public ProductA() {
        System.out.println("ProductA");
    }
}
/**
 * 产品B
 * ProductB 实现 Product接口
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public class ProductB implements Product {
    public ProductB() {
        System.out.println("ProductB");
    }
}

/**
 * 简单工厂
 * 通过参数实现创建不同的对象
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public class SimpleFactory {

    private static final String PRODUCT_A = "ProductA";
    private static final String PRODUCT_B = "ProductB";

    /**
     * 方式二
     * 根据参数创建不同产品
     *
     * @param productType
     * @return
     */
    public static Product createProduct(String productType) {
        if (PRODUCT_A.equals(productType)) {
            return new ProductA();
        } else if (PRODUCT_B.equals(productType)) {
            return new ProductB();
        } else {
            return null;
        }
    }

    /**
     * 方式一
     * 根据参数创建不同产品
     *
     * @param productType
     * @return
     */
    public static Product createPro(String productType) {
        Product product = null;
        switch (productType) {
            case PRODUCT_A:
                product = new ProductA();
                break;

            case PRODUCT_B:
                product = new ProductB();
                break;

            default:
                product = null;
                break;
        }
        return product;
    }

}


/**
 * 简单工厂测试类
 * <p>
 * 优点
 * (1)简单工厂包含必要的判断逻辑,简单工厂实现了对象的创建和使用的分离。
 * (2)客户端无需知道所创建的具体产品类的类名,只需要具体产品类对应的参数即可!
 * (3)在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性
 * <p>
 * 缺点
 * (1)工厂类的职责过重,从类图中可以看出简单工厂中的逻辑判断语句,它一旦有问题,整个系统都要出问题
 * (2)在添加新的类的时候,那么系统中的简单工厂类就要修改,违反了开放——封闭原则!这样及其不利于系统的扩展和维护!
 * (3)简单工厂的静态方法,使得工厂角色无法形成基于继承的等级结构!
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public class SimpleFactoryTest {

    private static final String PRODUCT_A = "ProductA";
    private static final String PRODUCT_B = "ProductB";

    @Test
    public void simpleFactoryTest() {
        // 方式一创建产品AB
        Product productA = SimpleFactory.createProduct(PRODUCT_A);
        Product productB = SimpleFactory.createProduct(PRODUCT_B);
        System.out.println("方式一创建产品AB:" + productA + "," + productB);

        // 方式二创建产品AB
        Product proA = SimpleFactory.createPro(PRODUCT_A);
        Product proB = SimpleFactory.createPro(PRODUCT_B);
        System.out.println("方式二创建产品AB:" + proA + "," + proB);
    }
}

3.2 工厂模式实现

/**
 * 产品C
 * ProductC 实现 Product接口
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public class ProductC implements Product {
    public ProductC() {
        System.out.println("ProductC");
    }
}
/**
 * 工厂接口:工厂的工厂
 * 工厂:不同的产品由不同的工厂实现,
 * 简单工厂: 简单工厂实现所有对象的创建
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public interface Factory {
    Product createProduct();
}
/**
 * 工厂A
 * 由工厂A创建产品A
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public class FactoryA implements Factory {
    @Override
    public Product createProduct() {
        return new ProductA();
    }
}
/**
 * 工厂B
 * 由工厂B创建产品B
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public class FactoryB implements Factory {
    @Override
    public Product createProduct() {
        return new ProductB();
    }
}
/**
 * 工厂C
 * 由工厂C创建产品C
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public class FactoryC implements Factory {
    @Override
    public Product createProduct() {
        return new ProductC();
    }
}

/**
 * 工厂测试类
 * 通过工厂A创建产品A,工厂B创建产品B,工厂C创建产品C
 *
 * 优点:
 * (1)不同的工厂创建不同的产品,隐藏了细节。
 * (2)在增加修改新的运算类的时候不用修改代码,只需要增加对应的工厂就好,完全符合开放——封闭性原则!
 * (3)创建对象的细节完全封装在具体的工厂内部,而且有了抽象的工厂类,所有的具体工厂都继承了自己的父类!完美的体现了多态性!
 *
 * 缺点:
 * (1)在增加新的产品(对应UML图的算法)时,也必须增加新的工厂类,会带来额外的开销
 * (2)抽象层的加入使得理解程度加大
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public class FactoryTest {

    @Test
    public void factoryTest() {
        Factory factoryA = new FactoryA();
        factoryA.createProduct();

        Factory factoryB = new FactoryB();
        factoryB.createProduct();

        Factory factoryC = new FactoryC();
        factoryC.createProduct();

    }
}

3.3 抽象工厂实现

/**
 * 礼品接口
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public interface Gift {
}
/**
 * 礼品A
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public class GiftA implements Gift {
    public GiftA() {
        System.out.println("GiftA");
    }
}
/**
 * 礼品B
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public class GiftB implements Gift {
    public GiftB() {
        System.out.println("GiftB");
    }
}
/**
 * 抽象工厂
 * 抽象工厂模式是工厂方法模式的进一步延伸,就是可以生产不止一种产品,由于它提供了功能更为强大的工厂类并且具备较好的可扩展性.
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public interface AbstractFactory {
    Product createProduct();

    Gift createGift();
}
/**
 * 工厂A
 * 由工厂A创建产品A与礼品A
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public class AbstractFactoryA implements AbstractFactory {
    @Override
    public Product createProduct() {
        return new ProductA();
    }

    @Override
    public Gift createGift() {
        return new GiftA();
    }
}
/**
 * 工厂B
 * 由工厂B创建产品B与礼品B
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public class AbstractFactoryB implements AbstractFactory {
    @Override
    public Product createProduct() {
        return new ProductB();
    }

    @Override
    public Gift createGift() {
        return new GiftB();
    }
}

/**
 * 抽象工厂测试类
 * 抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类,
 * 抽象工厂模式较好的实现了“开放-封闭”原则,是三个模式中较为抽象,并具一般性的模式。
 * 我们在使用中要注意使用抽象工厂模式的条件。
 *
 * @author 20023262
 * @date 2020/12/4
 * @since 1.0
 */
public class AbstractFactoryTest {

    @Test
    public void abstractFactoryTest() {
        AbstractFactory abstractFactoryA = new AbstractFactoryA();
        abstractFactoryA.createProduct();
        abstractFactoryA.createGift();

        AbstractFactory abstractFactoryB = new AbstractFactoryB();
        abstractFactoryB.createProduct();
        abstractFactoryB.createGift();

    }

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值