同步操作将从 turnon/blog 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
title: 设计模式之工厂方法模式
date: 2015-06-03 10:03:00
categories:
- 设计
- 设计模式
tags:
- 设计
- 设计模式
permalink: /pages/65724c/
工厂方法模式 (Factory Method)是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 让子类决定实例化对象的类型。
简单工厂模式相比于工厂方法模式
优点:工厂类中包含必要的逻辑判断,可根据客户端的选择条件动态实例化需要的类。对于客户端来说,去除了对具体产品的依赖。
缺点:违背了开放封闭原则。 每添加一个新的产品,都需要对原有类进行修改。增加维护成本,且不易于维护。
开放封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
【Product】
定义产品对象的接口。
abstract class Product {
public abstract void use();
}
【ConcreteProduct】
实现 Product
接口。
class ConcreteProduct extends Product {
public ConcreteProduct() {
System.out.println("创建 ConcreteProduct 产品");
}
@Override
public void Use() {
System.out.println("使用 ConcreteProduct 产品");
}
}
【Creator】
声明工厂方法,它会返回一个产品类型的对象。 Creator 也可以实现一个默认的工厂方法 factoryMethod()
,以返回一个默认的具体产品类型。
interface Creator {
public Product factoryMethod();
}
【ConcreteCreator】
覆写 Creator 中的工厂方法 factoryMethod()
。
class ConcreteCreator implements Creator {
@Override
public Product factoryMethod() {
return new ConcreteProduct();
}
}
【客户端】
public class factoryMethodPattern {
public static void main(String[] args) {
Creator factory = new ConcreteCreator();
Product product = factory.factoryMethod();
product.Use();
}
}
【输出】
创建 ConcreteProduct 产品
使用 ConcreteProduct 产品
以下示例演示了如何使用工厂方法开发跨平台 UI (用户界面) 组件, 并同时避免客户代码与具体 UI 类之间的耦合。
基础对话框类使用不同的 UI 组件渲染窗口。 在不同的操作系统下, 这些组件外观或许略有不同, 但其功能保持一致。 Windows 系统中的按钮在 Linux 系统中仍然是按钮。
如果使用工厂方法, 就不需要为每种操作系统重写对话框逻辑。 如果我们声明了一个在基本对话框类中生成按钮的工厂方法, 那么我们就可以创建一个对话框子类, 并使其通过工厂方法返回 Windows 样式按钮。 子类将继承对话框基础类的大部分代码, 同时在屏幕上根据 Windows 样式渲染按钮。
如需该模式正常工作, 基础对话框类必须使用抽象按钮 (例如基类或接口), 以便将其扩展为具体按钮。 这样一来, 无论对话框中使用何种类型的按钮, 其代码都可以正常工作。
你可以使用此方法开发其他 UI 组件。 不过, 每向对话框中添加一个新的工厂方法, 你就离抽象工厂模式更近一步。 我们将在稍后谈到这个模式。
// 创建者类声明的工厂方法必须返回一个产品类的对象。创建者的子类通常会提供
// 该方法的实现。
class Dialog is
// 创建者还可提供一些工厂方法的默认实现。
abstract method createButton():Button
// 请注意,创建者的主要职责并非是创建产品。其中通常会包含一些核心业务
// 逻辑,这些逻辑依赖于由工厂方法返回的产品对象。子类可通过重写工厂方
// 法并使其返回不同类型的产品来间接修改业务逻辑。
method render() is
// 调用工厂方法创建一个产品对象。
Button okButton = createButton()
// 现在使用产品。
okButton.onClick(closeDialog)
okButton.render()
// 具体创建者将重写工厂方法以改变其所返回的产品类型。
class WindowsDialog extends Dialog is
method createButton():Button is
return new WindowsButton()
class WebDialog extends Dialog is
method createButton():Button is
return new HTMLButton()
// 产品接口中将声明所有具体产品都必须实现的操作。
interface Button is
method render()
method onClick(f)
// 具体产品需提供产品接口的各种实现。
class WindowsButton implements Button is
method render(a, b) is
// 根据 Windows 样式渲染按钮。
method onClick(f) is
// 绑定本地操作系统点击事件。
class HTMLButton implements Button is
method render(a, b) is
// 返回一个按钮的 HTML 表述。
method onClick(f) is
// 绑定网络浏览器的点击事件。
class Application is
field dialog: Dialog
// 程序根据当前配置或环境设定选择创建者的类型。
method initialize() is
config = readApplicationConfigFile()
if (config.OS == "Windows") then
dialog = new WindowsDialog()
else if (config.OS == "Web") then
dialog = new WebDialog()
else
throw new Exception("错误!未知的操作系统。")
// 当前客户端代码会与具体创建者的实例进行交互,但是必须通过其基本接口
// 进行。只要客户端通过基本接口与创建者进行交互,你就可将任何创建者子
// 类传递给客户端。
method main() is
this.initialize()
dialog.render()
使用示例: 工厂方法模式在 Java 代码中得到了广泛使用。 当你需要在代码中提供高层次的灵活性时, 该模式会非常实用。
核心 Java 程序库中有该模式的应用:
java.util.Calendar#getInstance()
java.util.ResourceBundle#getBundle()
java.text.NumberFormat#getInstance()
java.nio.charset.Charset#forName()
java.net.URLStreamHandlerFactory#createURLStreamHandler(String)
(根据协议返回不同的单例对象)java.util.EnumSet#of()
javax.xml.bind.JAXBContext#createMarshaller()
及其他类似的方法。识别方法: 工厂方法可通过构建方法来识别, 它会创建具体类的对象, 但以抽象类型或接口的形式返回这些对象。
还是以 简单工厂模式 里的例子来进行说明。
如何实现一个具有加减乘除基本功能的计算器?
两种模式的 Product
和 ConcreteProduct
角色代码没有区别,不再赘述。
差异在于 Factory
角色部分,以及客户端部分,请在代码中体会。
【Creator 角色】
// Creator 角色,定义返回产品实例的公共工厂方法
interface OperationFactory {
public Operation factoryMethod();
}
【ConcreteCreator 角色】
和简单工厂模式相比,每一种产品都会有一个具体的工厂类负责生产实例。
// ConcreteCreator 角色,具体实现 Creator 中的方法
class AddFactory implements OperationFactory {
@Override
public Operation factoryMethod() {
return new Add();
}
}
// ConcreteCreator 角色,具体实现 Creator 中的方法
class SubFactory implements OperationFactory {
@Override
public Operation factoryMethod() {
return new Sub();
}
}
// ConcreteCreator 角色,具体实现 Creator 中的方法
class MulFactory implements OperationFactory {
@Override
public Operation factoryMethod() {
return new Mul();
}
}
// ConcreteCreator 角色,具体实现 Creator 中的方法
class DivFactory implements OperationFactory {
@Override
public Operation factoryMethod() {
return new Div();
}
}
【Client 角色】
与简单工厂模式中无需关注具体创建不同,工厂模式中需要指定具体工厂,以负责生产具体对应的产品。
// Client 角色,需要指定具体工厂,以负责生产具体产品
public class factoryMethodPattern {
public static void main(String[] args) {
OperationFactory factory = new SubFactory();
Operation oper = factory.factoryMethod();
oper.numA = 3;
oper.numB = 2;
double result = oper.getResult();
System.out.println("result = " + result);
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。