第二章 创建型模式
1、创建型模式概述
-
主要特点
将对象的创建与使用分离”,这样可以降低系统的耦合度。 -
创建型模式分为以下几种:
⑴单例(Singleton)模式 :某个类只能生成一个实例,该类提供了一个全 局访问点供外部获取该实例,其拓展是有限多例模式。
⑵ 原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克 隆出多个和原型类似的新实例。
⑶ 工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子 类决定生产什么产品。
⑷ 抽象工厂(Abstract Factory)模式:提供一个创建产品族的接口,其每 个子类可以生产一系列相关的产品。
⑸ 建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分, 然后根据不同需要分别创建它们,最后构建成该复杂对象。
2、工厂方法模式(Factory method)
(1)模式的定义与特点
- 定义:定义一个创建产品对象的工厂接口,将产品对象的实际创 建工作推迟到具体子工厂类当中。
- 这满足创建型模式中所要求的“创建与使用相分离”的特点。
-
优点:用户知道具体工厂的名称就可得到所要的产品,无须知道产品的创建过程;满足开闭原则。
-
缺点:每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
(2)模式的结构与实现
1、结构
1)抽象工厂(Abstract Factory):提供了创建产品的接口,调用 者通过它访问具体工厂的工厂方法newProduct()来创建产品。
2)具体工厂(Concrete Factory):主要是实现抽象工厂中的抽象 方法,完成具体产品的创建。
3)抽象产品(Product):定义了产品的规范,描述了产品的主要 特性和功能。
4)具体产品(Concrete Product):实现了抽象产品角色所定义的 接口,由具体工厂来创建,它同具体工厂之间一一对应。
结构图:
2、实现
例:用工厂方法 模式设计畜牧场
- 有很多种类的 畜牧场,如养马场用于养 马,养牛场用于养牛。
代码:
抽象产品,动物类:
//抽象产品:动物类
interface Animal {
public void show();
}
具体产品,马类:
//具体产品:马类
class Horse implements Animal {
String horse;
public Horse() {
horse = "马";
}
public void show() {
// // 调用父类的show方法时显示
System.out.println(horse);
}
}
具体产品,牛类:
//具体产品:牛类
class Cattle implements Animal {
String cattle;
public Cattle() {
cattle = "牛";
}
public void show() {
// 调用父类的show方法时显示
System.out.println(cattle);
}
}
抽象工厂,畜牧场:
//抽象工厂:畜牧场
interface AnimalFarm {
// 创建产品,动物
public Animal newAnimal();
}
具体工厂,养马场:
//具体工厂:养马场
class HorseFarm implements AnimalFarm {
// 重写父类方法,创建具体动物
public Animal newAnimal() {
System.out.println("新马出生!");
// 创建并返回马
return new Horse();
}
}
具体工厂,养牛场:
//具体工厂:养牛场
class CattleFarm implements AnimalFarm {
public Animal newAnimal() {
System.out.println("新牛出生!");
return new Cattle();
}
}
config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<config>
// 养牛场
<className>CattleFarm</className>
</config>
ReadXML:该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
class ReadXML{
//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
public static Object getObject() {
try {
//创建文档对象
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;
// 对读取配置文件路径
doc = builder.parse(new File("src/chapter03/factoryMethod/config.xml"));
//获取包含类名的文本节点
NodeList nl = doc.getElementsByTagName("className");
Node classNode = nl.item(0).getFirstChild(); // classNode =CattleFarm
String cName = "chapter03.factoryMethod." + classNode.getNodeValue();
// cName : chapter03.factoryMethod.CattleFarm
//通过类名生成实例对象并将其返回
Class<?> c = Class.forName(cName);
Object obj = c.newInstance();
return obj; // return new CattleFarm();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
测试:
public class AnimalFarmTest {
public static void main(String[] args) {
try {
// 抽象产品
Animal a;
// 抽象工厂
AnimalFarm af;
// 读取配置文件中的具体工厂
af = (AnimalFarm) ReadXML2.getObject();
// 通过获得的具体工厂创建具体产品
a = af.newAnimal();
// 展示
a.show();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
(3)应用场景
- 客户只知道创建产品的工厂名,而不知道具体的产品名。如:
TCL电视工厂、海信电视工厂等; - 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工
厂只提供创建产品的接口。 - 客户不关心创建产品的细节,只关心产品的品牌
(4)扩展
- 当需要生成的产品不多且不会增加,一个具体工厂类就可以完成任务时,可删除抽象工厂类。这时工厂方法模式将退化到简单工厂模式。