创建型模式之工厂方法模式(3)

                                     工厂模式三兄弟之工厂方法模式


1.什么是工厂方法?  

工厂方法模式(FACTORY METHOD)是一种常用的创建型设计模式,此模式的核心精神是封装类中不变的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有四个角色,分别是抽象工厂,具体工厂,抽象产品,具体产品. 工厂方法模式也是简单工厂的进化版本,为什么这么说呢,继续往下看就明白了.

 

2.为什么用工厂方法模式?

在上一篇中介绍过 简单工厂 了,虽然说简单工厂已经可以解决部分问题了,但是也存在一个很严重的缺陷,当需求变化小的时候可能不太容易发现,但是当需求(具体产品)的更改持续增加的时候,就要频繁的更改工厂的代码,这也就违背了开闭原则,显然是不好的设计,当判断逻辑变得臃肿时,改一个逻辑就会变得小心翼翼外加困难重重,所以工厂方法模式也就这么应运而生了,而他是怎么解决这个问题的呢?其实也就是把开闭原则利用上,把其中个性化的部分提取出来设置成独立的个体,然后通过注入的方式去让整个工厂更灵活,更容易拓展,也就达到了解耦和复用的作用.

 

3.工厂方法模式怎么用?

先来看看简单工厂模式的UML模型:

由此可以看出,抽象工厂模式主要是由四部分组成:抽象工厂,具体工厂,抽象产品,具体产品;通过个性化后的工厂生产个性化的对象,已达到相互隔离的效果.同时也满足了开闭原则.它即继承了简单工厂模式的优点,又还弥补了简单工厂模式的不足.所以在使用上来说,工厂方法模式也是使用频率最高的设计模式之一.下面来看具体代码:

 

抽象工厂:

/**
 * @author zhangcq
 * @Description: 抽象工厂
 * @Time: 2019/3/4 14:04
 * @Version 1.0
 */
public abstract class LogsFactory {

    public void print() {
        Logs logger = this.createLogger();
        logger.print();

    }

    protected abstract Logs createLogger();

}

DB工厂:

/**
 * @author zhangcq
 * @Description: DB工厂
 * @Time: 2019/3/8 13:36
 * @Version 1.0
 */
public class DBLogsFactory extends LogsFactory {
    @Override
    protected Logs createLogger() {
        return new LogsDB();
    }
}

File工厂:

/**
 * @author zhangcq
 * @Description: File工厂
 * @Time: 2019/3/8 13:36
 * @Version 1.0
 */
public class FileLogsFactory extends LogsFactory {
    @Override
    protected Logs createLogger() {
        return new LogsFile();
    }
}

抽象产品:

/**
 * @author zhangcq
 * @Description: 抽象产品
 * @Time: 2019/3/4 14:04
 * @Version 1.0
 */
public interface Logs {

    void print();
}

DB产品:

/**
 * @author zhangcq
 * @Description: DB产品
 * @Time: 2019/3/4 14:16
 * @Version 1.0
 */
public class LogsDB implements Logs {
    @Override
    public void print() {
        System.out.println("将日志输出到数据库...");
    }
}

File产品:

/**
 * @author zhangcq
 * @Description: File产品
 * @Time: 2019/3/4 14:17
 * @Version 1.0
 */
public class LogsFile implements Logs {
    @Override
    public void print() {
        System.out.println("将日志输出到文件...");
    }
}

客户端:

/**
 * @author zhangcq
 * @Description: 客户端
 * @Time: 2019/3/4 14:18
 * @Version 1.0
 */
public class LogsClient {

    public static void main(String[] args) {
        LogsFactory logsFactory;
        logsFactory = new DBLogsFactory();
        logsFactory.print();
        logsFactory = new FileLogsFactory();
        logsFactory.print();

    }
}

 

 4.工厂方法模式总结

 1. 主要优点

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

       (1) 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。

       (2) 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够让工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,就正是因为所有的具体工厂类都具有同一抽象父类。

       (3) 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了,这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

 

      2. 主要缺点

     工厂方法模式的主要缺点如下:

      (1) 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。

      (2) 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

 

       3. 适用场景

       在以下情况下可以考虑使用工厂方法模式:

       (1) 客户端不知道它所需要的对象的类。在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建,可将具体工厂类的类名存储在配置文件或数据库中。

       (2) 抽象工厂类通过其子类来指定创建哪个对象。在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
 

_____________________________________________________________________________________________________代码地址:github

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值