java设计模式之(二)-工厂模式(三种)

这里写目录标题

    • 一、概述
      • 1.1 定义
      • 1.2 优点
      • 1.3 缺点
      • 1.4 为什么要用工厂模式
    • 二、简单工厂模式
      • 2.1 介绍
      • 2.2 角色分配
      • 2.3 使用场景
      • 2.4 实例讲解
      • 2.5 使用反射机制改善简单工厂
    • 三、工厂方法模式
      • 3.1 介绍
      • 3.2 角色分配
      • 3.3 适用场景
      • 3.4 实例讲解
      • 3.5 优缺点说明:
    • 四、抽象工厂模式
      • 4.1 介绍
      • 4.2 角色分配
      • 4.3 适用场景
      • 4.4 实例讲解
      • 4.5 优缺点说明
    • 五、总结:

一、概述

1.1 定义

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。定义一个创建对象的工厂接口,将对象的实际创建工作推迟到具体子工厂类当中。

1.2 优点

1、一个调用者想创建一个对象,只要知道其名称就可以了。
2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
3、屏蔽产品的具体实现,调用者只关心产品的接口。

1.3 缺点

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

1.4 为什么要用工厂模式

(1) 解耦 :把对象的创建和使用的过程分开
(2)降低代码重复: 如果创建某个对象的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。
(3) 降低维护成本 :由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建某个对象的地方去逐个修正,只需要在工厂里修改即可,降低维护成本。

二、简单工厂模式

2.1 介绍

严格的说,简单工厂模式并不是23种常用的设计模式之一,它只算工厂模式的一个特殊实现。它违背了我们在设计模式七大原则中所说的“开闭原则”(虽然可以通过反射的机制类避免,后面会提到)。因为每次要新添加一个功能,都需要在switch-case语句(或者if-else语句)中去修改代码,添加分支条件。

2.2 角色分配

组成(角色)关系作用
抽象产品(Product)具体产品的父类描述产品的公共接口
具体产品(Concrete Product)抽象产品的子类;工厂类创建的目标类描述生产的具体产品
工厂(Creator)被外界调用根据传入不同的参数从而创建不同具体产品类的实例

2.3 使用场景

1.需要创建的对象较少。
2.客户端不关心对象的创建过程。

2.4 实例讲解

1.创建抽象产品类,定义具体产品的公共接口

public abstract class Car {abstract void run();
}

2.创建具体产品类,定义生产的具体产品

//具体产品-奥迪车
public class Audi extends Car {@Overridevoid run() {System.out.println("奥迪车,跑起来贼稳...");}
}//具体产品-宝马车
public class Bmw extends Car {@Overridevoid run() {System.out.println("宝马车,跑起来贼溜...");}
}

3.创建工厂类,提供具体的产品对象

public class CarFactory {public static Car getCar(String type) {Car car = null;if ("Bmw".equalsIgnoreCase(type)) {car = new Bmw();} else if ("Audi".equalsIgnoreCase(type)) {car = new Audi();}return car;}
}

4.外界通过调用工厂类的静态方法,传入不同参数从而创建不同具体产品类的实例

public class Test {public static void main(String[] args) {//获取奥迪车实例,并执行方法Car audi = CarFactory.getCar("audi");audi.run();//获取宝马车实例,并执行方法Car bmw = CarFactory.getCar("bmw");bmw.run();}
}

结果输出:

奥迪车,跑起来贼稳...
宝马车,跑起来贼溜...

这样的实现有个问题,如果我们新增产品类的话,就需要修改工厂类中的getCar()方法,这很明显不符合开闭原则的

2.5 使用反射机制改善简单工厂

public class CarFactoryNew {/*** 利用反射解决简单工厂每次增加新产品类都要修改产品工厂的弊端* */public static Object getClass(Class<? extends Car> clazz) {Object obj = null;try {obj = Class.forName(clazz.getName()).newInstance();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return obj;}
}

此时增加比亚迪汽车,并进行测试

//比亚迪汽车
public class Byd extends Car{@Overridevoid run() {System.out.println("比亚迪汽车,跑起来贼快");}
}//测试方法
public class TestNew {public static void main(String[] args) {Audi audi = (Audi) CarFactoryNew.getClass(Audi.class);audi.run();Bmw bmw = (Bmw) CarFactoryNew.getClass(Bmw.class);bmw.run();Byd byd = (Byd) CarFactoryNew.getClass(Byd.class);byd.run();}
}

输出结果:

奥迪车,跑起来贼稳...
宝马车,跑起来贼溜...
比亚迪汽车,跑起来贼快

三、工厂方法模式

3.1 介绍

简单工厂模式最大的缺点就是当有新产品要加入到系统中时,必须修改工厂类,这违背了开闭原则。在工厂方法中,我们不在提供统一的工厂类来创建所有的产品对象,而是针对不同的产品提供不同的工厂。
工厂方法模式将类的实例化推迟到了工厂类的子类中完成,即由子类来决定应该实例哪一个类。工厂方法模式是简单工厂模式的延伸,是使用频率最高的设计模式之一,是很多开源框架与API类库的核心模式。

3.2 角色分配

组成(角色)关系作用
抽象产品(Product)具体产品的父类描述产品的公共接口
具体产品(Concrete Product)抽象产品的子类;工厂类创建的目标类描述生产的具体产品
抽象工厂(Creator)具体工厂的父类描述具体工厂的公共接口
具体工厂(Concrete Creator)抽象工厂的子类;被外接调用描述具体工厂;实现FactoryMethod工厂方法创建产品的实例

3.3 适用场景

客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体的工厂类创建。
将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无需关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。

3.4 实例讲解

创建抽象工厂类

public interface Factory {Car getCar();
}

创建具体工厂类

//创建比亚迪汽车工厂
public class BydFactory implements Factory {@Overridepublic Car getCar() {return new Byd();}
}//创建奥迪汽车工厂
public class AudiFactory implements Factory {@Overridepublic Car getCar() {return new Audi();}
}

测试方法

public class Test {public static void main(String[] args) {//奥迪汽车AudiFactory audiFactory = new AudiFactory();audiFactory.getCar().run();//比亚迪汽车BydFactory bydFactory = new BydFactory();bydFactory.getCar().run();}
}

输出结果:

奥迪车,跑起来贼稳...
比亚迪汽车,跑起来贼快

3.5 优缺点说明:

符合开闭原则,新增加一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可;
添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统复杂度;
一个具体工厂只能创建一种具体的产品;

四、抽象工厂模式

4.1 介绍

工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题,但由于工厂方法模式中的每个工厂只能生产一类产品,可能会导致系统中存在大量的工厂类,势必增加系统的开销。此时,我们可以考虑将一些相关的产品组成一个“产品族”,由同一个工厂来统一生产

4.2 角色分配

组成(角色)关系作用
抽象产品族(AbstractProduct)抽象产品的父类描述抽象产品的公共接口
抽象产品(Product)具体产品的父类描述产品的公共接口
具体产品(Concrete Product)抽象产品的子类;工厂类创建的目标类描述生产的具体产品
抽象工厂(Creator)具体工厂的父类描述具体工厂的公共接口
具体工厂(Concrete Creator)抽象工厂的子类;被外接调用描述具体工厂;实现FactoryMethod工厂方法创建产品的实例

4.3 适用场景

一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是很重要的,用户无须关心对象的创建过程,将对象的创建和使用解耦
系统中有多于一个的产品族,而每次只使用其中某一产品族。可以通过配置文件等方式来使得用户可以动态改变产品族,也可以很方便地增加新的产品族
产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或删除已有的产品登记结构。

4.4 实例讲解

1.创建抽象工厂类,定义具体工厂的公共接口

public abstract class Factory {abstract Mobile makeMobile();abstract Ipad makeIpad();
}

2.创建抽象产品类,定义具体产品的公共接口

//手机产品抽象类
public abstract class Mobile {abstract void show();
}//平板产品抽象类
public abstract class Ipad {abstract void show();
}

3.创建具体产品类,定义生产的具体产品

//华为手机产品
public class HuaWeiMobile extends Mobile {@Overridevoid show() {System.out.println("华为手机,您手中的世界500强。。。");}
}//小米手机产品
public class XiaoMiMobile extends Mobile {@Overridevoid show() {System.out.println("小米手机,为发烧而生");}
}//华为平板产品
public class HuaWeiIpad extends Ipad {@Overridevoid show() {System.out.println("华为平板,很不错。。。");}
}//小米平板产品
public class XiaoMiIpad extends Ipad {@Overridevoid show() {System.out.println("小米平板,很棒。。。");}
}

4.创建具体工厂类,定义创建对应具体产品实例的方法

/*** 

* 华为工厂*

** @author hpb*/ public class HuaWeiFactory extends Factory {@OverrideMobile makeMobile() {return new HuaWeiMobile();}@OverrideIpad makeIpad() {return new HuaWeiIpad();} }/***

* 小米工厂*

** @author hpb*/ public class XiaoMiFactory extends Factory {@OverrideMobile makeMobile() {return new XiaoMiMobile();}@OverrideIpad makeIpad() {return new XiaoMiIpad();} }

测试

public class Test {public static void main(String[] args) {HuaWeiFactory huaWeiFactory = new HuaWeiFactory();XiaoMiFactory xiaoMiFactory = new XiaoMiFactory();//生产华为手机huaWeiFactory.makeMobile().show();//生产华为平板huaWeiFactory.makeIpad().show();//生产小米手机xiaoMiFactory.makeMobile().show();//生产小米平板xiaoMiFactory.makeIpad().show();}
}

输出结果

华为手机,您手中的世界500强。。。
华为平板,很不错。。。
小米手机,为发烧而生
小米平板,很棒。。。

4.5 优缺点说明

1.抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展;
2.新增一种产品类时比如(苹果手机和平板),只需要增加相应的具体产品类和相应的工厂子类即可,符合开闭原则
3.抽象工厂很难支持新种类产品的变化,需要添加新的产品时(比如新增电视机产品),就必须修改抽象工厂的接口以及所有的子类工厂,这样也就违背了开闭原则
4.对于新的产品族符合开闭原则;对于新的产品种类不符合开闭原则,这一特性称为开闭原则的倾斜性。

五、总结:

以上介绍的三种工厂模式有各自的应用场景,实际应用时能解决问题满足需求即可,可灵活变通,无所谓高级与低级。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部