博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式之工厂模式
阅读量:3908 次
发布时间:2019-05-23

本文共 12251 字,大约阅读时间需要 40 分钟。

1.2 工厂模式

源代码地址:

文章目录

1.2.1 简单工厂模式

(1)概念

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

(2)适用场景

我们明确地计划不同条件下创建不同实例时使用工厂模式。

使用场景: 1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3、设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口。

**注意事项:**作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

(3)代码示例

整体类图

首先创建抽象类交通工具类:Vehicle

package com.alibaba.design.factorypattern.simplefactory;/** * @author zhouyanxiang * @create 2020-07-2020/7/28-9:49 */public abstract class Vehicle {    private String name;    public Vehicle(String name) {        this.name = name;        System.out.println(name);    }    @Override    public String toString(){        return "Vehicle" + name;    }    abstract public Vehicle newInstance();}

然后分别创建三个实体工具类Car、Bike、Truck

  • Car
package com.alibaba.design.factorypattern.simplefactory;/** * @author zhouyanxiang * @create 2020-07-2020/7/28-9:50 */public class Car  extends Vehicle {    private String name;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Car(String name) {        super(name);        System.out.println(name);    }    @Override    public String toString(){        return "Car:" + name;    }    @Override    public Vehicle newInstance() {        return new Car("Car ...");    }}
  • Bike
package com.alibaba.design.factorypattern.simplefactory;/** * @author zhouyanxiang * @create 2020-07-2020/7/28-10:06 */public class Bike extends Vehicle {    public Bike(String name) {        super(name);    }    @Override    public Vehicle newInstance() {        return new Bike("Bike ...");    }}
  • Truck
package com.alibaba.design.factorypattern.simplefactory;/** * @author zhouyanxiang * @create 2020-07-2020/7/28-10:07 */public class Truck extends Vehicle {    public Truck(String name) {        super(name);    }    @Override    public Vehicle newInstance() {        return new Truck("Truck ...");    }}
  • 创建交通工具工厂类VehicleFactory

    避免反射机制,使用注册新Vehicle类的类似工厂类,不再将类添加到map对象中,而是将要注册得到每种对象实例添加其中。每个产品类都能够创造自己的实例。

package com.alibaba.design.factorypattern.simplefactory;import java.util.HashMap;import java.util.Map;/** * @author zhouyanxiang * @create 2020-07-2020/7/28-9:47 */public class VehicleFactory {    private Map
registeredProducts = new HashMap<>(); public Vehicle createVehicle(String vehicleName){ return registeredProducts.get(vehicleName).newInstance(); } public void registerVehicle(String vehicleName,Vehicle vehicle){ registeredProducts.put(vehicleName,vehicle); }}
  • 客户端测试类
package com.alibaba.design.factorypattern.simplefactory;/** * @author zhouyanxiang * @create 2020-07-2020/7/28-9:54 */public class Test {    public static void main(String[] args) {        Vehicle vehicle = new Vehicle("A Car") {            @Override            public Vehicle newInstance() {                return new Car(" audi ");            }        };//        Vehicle vehicle2 = new Car("A Car");//        System.out.println(vehicle.toString());//        System.out.println(vehicle2.toString());    }}
(4)模式在源码中的体现

在JDK源码中 ,java.util.Calendar使用了工厂模式的简单工厂模式

public static Calendar getInstance(TimeZone zone,                                   Locale aLocale){    return createCalendar(zone, aLocale);}private static Calendar createCalendar(TimeZone zone,Locale aLocale){    CalendarProvider provider =        LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)                             .getCalendarProvider();    if (provider != null) {        try {            return provider.getInstance(zone, aLocale);        } catch (IllegalArgumentException iae) {            // fall back to the default instantiation        }    }    Calendar cal = null;    if (aLocale.hasExtensions()) {        String caltype = aLocale.getUnicodeLocaleType("ca");        if (caltype != null) {            switch (caltype) {            case "buddhist":            cal = new BuddhistCalendar(zone, aLocale);                break;            case "japanese":                cal = new JapaneseImperialCalendar(zone, aLocale);                break;            case "gregory":                cal = new GregorianCalendar(zone, aLocale);                break;            }        }    }    if (cal == null) {        // If no known calendar type is explicitly specified,        // perform the traditional way to create a Calendar:        // create a BuddhistCalendar for th_TH locale,        // a JapaneseImperialCalendar for ja_JP_JP locale, or        // a GregorianCalendar for any other locales.        // NOTE: The language, country and variant strings are interned.        if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {            cal = new BuddhistCalendar(zone, aLocale);        } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"                   && aLocale.getCountry() == "JP") {            cal = new JapaneseImperialCalendar(zone, aLocale);        } else {            cal = new GregorianCalendar(zone, aLocale);        }    }    return cal;}
(5)简单工厂模式的优缺点
  • 优点:

    1、一个调用者想创建一个对象,只要知道其名称就可以了。

    2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。

    3、屏蔽产品的具体实现,调用者只关心产品的接口。

  • **缺点:**每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

1.2.2 抽象工厂模式

(1) 概念

抽象工厂模式,对方法工厂模式进行抽象。

(2)适用场景

当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。说的更明白一点,就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。

(3)代码实例

类图

还是通过交通工具这一事例来讲述,

Vehicle接口,交通工具具有出行的作用,有一个toTravel()方法

package com.alibaba.design.factorypattern.factorymethod;/** * @author zhouyanxiang * @create 2020-07-2020/7/28-10:32 */public interface  Vehicle {    void toTravel();}

抽象的自行车类实现Vehicle接口

package com.alibaba.design.factorypattern.factorymethod;/** * @author zhouyanxiang * @create 2020-07-2020/7/30-18:20 */public abstract class Bike implements Vehicle {    public abstract void toTravel();}

抽象的汽车类实现Vehicle接口

package com.alibaba.design.factorypattern.factorymethod;/** * @author zhouyanxiang * @create 2020-07-2020/7/30-18:19 */public abstract class Car implements Vehicle {    public abstract void toTravel();}

实际的ChinaBikeFactory继承Bike类,重写出行toTravel()方法

package com.alibaba.design.factorypattern.factorymethod;/** * @author zhouyanxiang * @create 2020-07-2020/7/28-10:55 */public class ChinaBikeFactory extends Bike {    @Override    public void toTravel() {        System.out.println("In China,I will Choose bike to travel");    }}

实际的ChinaCarFactory继承Bike类,重写出行toTravel()方法

package com.alibaba.design.factorypattern.factorymethod;/** * @author zhouyanxiang * @create 2020-07-2020/7/30-20:05 */public class ChinaCarFactory extends Car{    @Override    public void toTravel() {        System.out.println("In China,I will choose car to travel");    }}

实际的EnglandBikeFactory继承Bike类,重写出行toTravel()方法

package com.alibaba.design.factorypattern.factorymethod;/** * @author zhouyanxiang * @create 2020-07-2020/7/30-18:36 */public class EnglandBikeFactory extends Bike {    @Override    public void toTravel() {        System.out.println("In England,I will Choose bike to travel");    }}

实际的EnglandCarFactory继承Bike类,重写出行toTravel()方法

package com.alibaba.design.factorypattern.factorymethod;/** * @author zhouyanxiang * @create 2020-07-2020/7/30-20:06 */public class EnglandCarFactory extends Car {    @Override    public void toTravel() {        System.out.println("In England,I will choose car to travel");    }}

VehicleFactory接口,用来实例化两种交通工具的出行方法

package com.alibaba.design.factorypattern.factorymethod;/** * @author zhouyanxiang * @create 2020-07-2020/7/28-10:25 */public interface  VehicleFactory {    // 实例化单车出行模式    public Vehicle bikeToTravel();    // 实例化小汽车出行模式    public Vehicle carToTravel();}

ChinaFactory实现VehicleFactory接口

package com.alibaba.design.factorypattern.factorymethod;/** * @author zhouyanxiang * @create 2020-07-2020/7/30-20:07 */public class ChinaFactory implements VehicleFactory {    @Override    public Vehicle bikeToTravel() {        return new ChinaBikeFactory();    }    @Override    public Vehicle carToTravel() {        return new ChinaCarFactory();    }}

EnglandFactory实现VehicleFactory接口

package com.alibaba.design.factorypattern.factorymethod;/** * @author zhouyanxiang * @create 2020-07-2020/7/30-20:08 */public class EnglandFactory implements VehicleFactory {    @Override    public Vehicle bikeToTravel() {        return new EnglandBikeFactory();    }    @Override    public Vehicle carToTravel() {        return new EnglandCarFactory();    }}

运行结果

(4)模式在源代码中的体现

在java.sql.Connection接口中

Connection接口就是一个抽象工厂接口,描述了不同产品等级Statement、PreparedStatement和CallableStatement,它们都位于抽象接口Statement产品等级结构中。

从MySQL(产品族)的Connection中获取的Statement、PreparedStatement和CallableStatement肯定都是MySQL,因为他们都是一个产品族,而从SQL Server中获取的肯定都是SQL Server对应的sql执行器。

假如以后又有新的数据库出现,想在Java中使用它就需要扩展产品族并实现相关接口即可,并不需要修改原有的接口。

参考:

https://blog.csdn.net/qq_23633427/article/details/107304244

(5)抽象工厂模式的优缺点
  • 优点

抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。

  • 缺点

产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。

1.2.3 工厂方法模式

(1)概念

​ 工厂方法模式(FACTORY METHOD)是一种常用的类创建型设计模式,此模式的核心精神是封装类中变化的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有四个角色,分别是抽象工厂;具体工厂;抽象产品;具体产品

可以看做是简单工厂模式的升级版;工厂方法模式就是一个工厂接口和多个工厂实现类,要增加一个新的产品,增加一个新的工厂实现类即可,针对之前的老的工厂实现类也不需要修改。

工厂方法模式相当于在简单工厂模式的基础上,增加了对于不同的产品进行多个不同工厂的实现类的添加,不同的工厂用于Get不同的产品,用于进行不同产品的具体生产。

Client进行调用的时候,直接通过识别不同工厂,然后通过工厂接口类提供的公共方法,即可进行接口方法调用,获取产品;还需要知道具体的产品接口,用于进行具体的产品信息的获取。

(2)适用场景

目标可以无限扩展,工厂类也要随之扩展,一对一存在,满足了开闭原则,但如果目标实现较多,工厂实现类也会增多,不简洁。

MyBatis中使用的比较多,事务模块和数据源模块都使用了工厂方法模式。

(3)代码实例

整体类图:

简单工厂模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改。假如增加其他品牌交通工具,工厂类需要修改,如何解决?就用到工厂方法模式,创建一个工厂接口和创建多个工厂实现类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

package com.alibaba.design.factorypattern.factorymothed;/** * @author zhouyanxiang * @create 2020-07-2020/7/30-21:45 */public interface Factory {    public Vehicle toTravel();}

交通工具接口Vehicle继承工厂接口

package com.alibaba.design.factorypattern.factorymothed;/** * @author zhouyanxiang * @create 2020-07-2020/7/30-21:43 */public interface Vehicle extends Factory{    public void toTravelInfo();}

CarFactory继承Factory

package com.alibaba.design.factorypattern.factorymothed;/** * @author zhouyanxiang * @create 2020-07-2020/7/30-21:48 */public class CarFactory implements Factory {    @Override    public Vehicle toTravel() {        return new Car();    }}

BikeFactory继承Factory

package com.alibaba.design.factorypattern.factorymothed;/** * @author zhouyanxiang * @create 2020-07-2020/7/30-21:49 */public class BikeFactory implements Factory {    @Override    public Vehicle toTravel() {        return new Bike();    }}

Bike继承BikeFactory并且实现Vehicle接口

package com.alibaba.design.factorypattern.factorymothed;/** * @author zhouyanxiang * @create 2020-07-2020/7/30-21:54 */public class Bike extends BikeFactory implements Vehicle {    @Override    public void toTravelInfo() {        System.out.println("Choose bike to travel");    }}

Car继承CarFactory并且实现Vehicle接口

package com.alibaba.design.factorypattern.factorymothed;/** * @author zhouyanxiang * @create 2020-07-2020/7/30-21:55 */public class Car extends CarFactory implements Vehicle {    @Override    public void toTravelInfo() {        System.out.println("Choose car to travel ");    }}

客户端测试类

package com.alibaba.design.factorypattern.factorymothed;/** * @author zhouyanxiang * @create 2020-07-2020/7/30-21:57 */public class Test {    public static void main(String[] args) {        Factory bikeFactory = new BikeFactory();        bikeFactory.toTravel().toTravelInfo();        System.out.println("==================");        Factory carFactory = new CarFactory();        carFactory.toTravel().toTravelInfo();    }}

最后输出结果

(4)工厂方法模式的在源码中的体现(在Android源码体现的比较多)

在Android源码中,ListActivity继承自Activity,将Activity作为工厂方法,生成具有ListView特点的Activity,对ListActivity的说明如下:

参考文章:https://www.cnblogs.com/yemeishu/archive/2013/01/08/2850586.html

(5)工厂方法模式的优缺点

满足了OCP(Open-Closed Principle)开闭原则,增加新的类需要修建新的工厂,增加了代码量。

如果同时需要修改多个工厂类的时候会很麻烦,而简单工厂模式只需要修改一个类,工厂方法模式是升级版的简单工厂模式。

你可能感兴趣的文章
spring相关面试题
查看>>
java面向对象设计的六大原则
查看>>
java面向对象6大原则2
查看>>
java线程池学习
查看>>
Java线程:概念与原理
查看>>
Java线程:并发协作-死锁
查看>>
《构建高性能web站点》笔记--基础架构篇
查看>>
以太坊源码分析---go-ethereum之p2p通信分析(1)
查看>>
以太坊源码分析---go-ethereum之p2p通信分析(2)
查看>>
groupcache源码分析
查看>>
go-metrics源码分析
查看>>
beego/cache源码分析---典型的工厂模式
查看>>
Boltdb源码分析(一)-------page结构
查看>>
Boltdb源码分析(二)----node结构
查看>>
Go标准库plugin源码分析----动态库使用
查看>>
开源代码学习-nsq(v0.1.1版本)源码分析
查看>>
开源代码学习-nsq(v0.1.5版本)源码分析
查看>>
开源代码protoactor-go[e866f39]源码分析
查看>>
开源代码protoactor-go源码分析-async schedule
查看>>
开源代码TarsGo-v1.0.0源码分析之transport
查看>>