Java设计模式编程中的工厂方法模式和抽象工厂模式
作者:goldensun 发布时间:2023-03-19 05:50:48
工厂方法模式
动机
创建一个对象往往需要复杂的过程,所以不适合包含在一个复合工厂中,当有新的产品时,需要修改这个复合的工厂,不利于扩展。
而且,有些对象的创建可以需要用到复合工厂访问不到的信息,所以,定义一个工厂接口,通过实现这个接口来决定实例化那个产品,这就是工厂方法模式,让类的实例化推迟到子类中进行。
目的
1. 定义一个接口,让子类决定实例化哪个产品。
2. 通过通用接口创建对象。
实现
1. 产品接口和具体产品很好理解。
2. 工厂类提供一个工厂方法,返回一个产品对象。但是这个工厂方法是抽象的。
3. 具体工厂类实现工厂方法,完成具体产品的创建。
//几个Button类
class Button{/* ...*/}
class WinButton extends Button{/* ...*/}
class MacButton extends Button{/* ...*/}
//它们的工厂类
interface ButtonFactory{
abstract Button createButton();
}
class WinButtonFactory implements ButtonFactory{
Button createButton(){
return new WinButton();
}
}
class MacButtonFactory implements ButtonFactory{
Button createButton(){
return new MacButton();
}
}
适用场景
1. 创建对象时有比较多重复的代码时,可以考虑使用工厂方法模式执行这些重复的部分。
2. 创建对象需要访问某些信息,而这些信息不应该包含在工厂类,那么可以让子类来实现对象的创建。
3. 需要集中管理对象的创建,保持程序的一致性时。
抽象工厂模式
定义
抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。客户端程序不需要知道(或关心)它从这些内部的工厂方法中获得对象的具体类型,因为客户端程序仅使用这些对象的通用接口。抽象工厂模式将一组对象的实现细节与他们的一般使用分离开来。
“工厂”是创建产品(对象)的地方,其目的是将产品的创建与产品的使用分离。抽象工厂模式的目的,是将若干抽象产品的接口与不同主题产品的具体实现分离开。这样就能在增加新的具体工厂的时候,不用修改引用抽象工厂的客户端代码。
使用抽象工厂模式,能够在具体工厂变化的时候,不用修改使用工厂的客户端代码,甚至是在运行时。然而,使用这种模式或者相似的设计模式,可能给编写代码带来不必要的复杂性和额外的工作。正确使用设计模式能够抵消这样的“额外工作”。
实现
1. AbstractFactory - 定义创建抽象产品的接口方法。
2. ConcreteFactory - 实现方法创建具体的产品。
3. AbstractProduct - 声明不同类型的产品的接口。
4. Product - 定义ConcreteFactory对应的具体产品,实现AbstractProduct接口。
5. Client - 使用AbstractFactory和AbstractProduct类。
abstract class AbstractProductA{
public abstract void operationA1();
public abstract void operationA2();
}
class ProductA1 extends AbstractProductA{
ProductA1(String arg){
System.out.println("Hello "+arg);
} // Implement the code here
public void operationA1() { };
public void operationA2() { };
}
class ProductA2 extends AbstractProductA{
ProductA2(String arg){
System.out.println("Hello "+arg);
} // Implement the code here
public void operationA1() { };
public void operationA2() { };
}
abstract class AbstractProductB{
//public abstract void operationB1();
//public abstract void operationB2();
}
class ProductB1 extends AbstractProductB{
ProductB1(String arg){
System.out.println("Hello "+arg);
} // Implement the code here
}
class ProductB2 extends AbstractProductB{
ProductB2(String arg){
System.out.println("Hello "+arg);
} // Implement the code here
}
abstract class AbstractFactory{
abstract AbstractProductA createProductA();
abstract AbstractProductB createProductB();
}
class ConcreteFactory1 extends AbstractFactory{
AbstractProductA createProductA(){
return new ProductA1("ProductA1");
}
AbstractProductB createProductB(){
return new ProductB1("ProductB1");
}
}
class ConcreteFactory2 extends AbstractFactory{
AbstractProductA createProductA(){
return new ProductA2("ProductA2");
}
AbstractProductB createProductB(){
return new ProductB2("ProductB2");
}
}
//Factory creator - an indirect way of instantiating the factories
class FactoryMaker{
private static AbstractFactory pf=null;
static AbstractFactory getFactory(String choice){
if(choice.equals("a")){
pf=new ConcreteFactory1();
}else if(choice.equals("b")){
pf=new ConcreteFactory2();
}
return pf;
}
}
// Client
public class Client{
public static void main(String args[]){
AbstractFactory pf=FactoryMaker.getFactory("a");
AbstractProductA product=pf.createProductA();
//more function calls on product
}
}
FactoryMaker类使用的是简单工厂模式,而具体工厂的实现用的是工厂方法模式。
适用场景
1. 一个系统要独立于它的产品的创建、组合和表示时。
2. 一个系统要由多个产品系列中的一个来配置时。
3. 需要强调一系列相关的产品对象的设计以便进行联合使用时。
4. 提供一个产品类库,而只想显示它们的接口而不是实现时。
优点
1. 具体产品从客户代码中被分离出来
2. 容易改变产品的系列
3. 将一个系列的产品族统一到一起创建
缺点
1. 在产品族中扩展新的产品是很困难的,它需要修改抽象工厂的接口和具体工厂。
猜你喜欢
- 博主在初学注解的时候看到网上的介绍大部分都是直接介绍用法或者功能,没有实际的应用场景,篇幅又很长导致学习的时候难以理解其意图,而且学完就忘Q
- List去重复,我们首先想到的可能是 利用List转Set集合,因为Set集合不允许重复。所以达到这个目的。 如果集合里面是简单对
- FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化
- 一、Java的前世为什么会产生Java?Java的特点是什么?从C语言开始讲,C语言是一种结构化语言,模块化编程,便于程序的调试,依靠非常全
- 本文我将要介绍一下mybatis的框架原理,以及mybatis的入门程序,实现用户的增删改查,她有什么优缺点以及mybatis和hibern
- 本文实例讲述了C++实现的O(n)复杂度内查找第K大数算法。分享给大家供大家参考,具体如下:题目:是在一组数组(数组元素为整数,可正可负可为
- 背景在使用Spring Boot Mvc的项目中,使用Long类型作为id的类型,但是当前端使用Number类型接收Long类型数据时,由于
- 如果想实现一个在桌面显示的悬浮窗,用Dialog、PopupWindow、Toast等已经不能实现了,他们基本都是在Activity之上显示
- 前言惰性计算(尽可能延迟表达式求值)是许多函数式编程语言的特性。惰性集合在需要时提供其元素,无需预先计算它们,这带来了一些好处。首先,您可以
- 时间处理相关类:1.java.util.Date:时间类2.java.text.DateFormat:时间格式化类(抽象类),实现类:jav
- 开篇:我们将前面的springboot整合H2内存数据库,实现单元测试与数据库无关性提供的Restful服务注册到spring cloud的
- 公司的svn的地址改变了,怎么办呢。自己本地的正在修改的项目怎么办呢?修改一下svn的服务器地址咯。1.就是先关闭ide,重新打开,然后选择
- strcpy函数详解如下1.函数介绍1.1.函数接口char * __cdecl strcpy(char * dst, const char
- 前言为什么用动静态库我们在实际开发中,经常要使用别人已经实现好的功能,这是为了开发效率和鲁棒性(健壮性);因为那些功能都是顶尖的工程师已经写
- 一、准备官网下载IntelliJ IDEA 2017 并安装好下载汉化包 (链接: https://pan.baidu.com/s/1JkU
- java的构造函数是一个非常重要的作用,首先java里的构造函数是可以重载的,而且因为也是可以继承在父类的构造函数,所以在子类里,首先必然是
- 1. 编写索引内容节点解释:settings:配置信息"number_of_replicas": 0 不需要备份(单节点
- 引言在多线程并发编程中synchronized和Volatile都扮演着重要的角色,Volatile是轻量级的synchronized,它在
- Spring spring-context-indexer依赖<dependencies> <d
- 导语相信大家无论是做前端还是做后端的,都被接口接口文档所折磨过,前端抱怨接口文档和后端给的不一致,后端抱怨写接口文档很麻烦,所以Swagge