第二章 创建型模式
1、创建型模式概述
-
主要特点
将对象的创建与使用分离”,这样可以降低系统的耦合度。 -
创建型模式分为以下几种:
⑴单例(Singleton)模式 :某个类只能生成一个实例,该类提供了一个全 局访问点供外部获取该实例,其拓展是有限多例模式。
⑵ 原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克 隆出多个和原型类似的新实例。
⑶ 工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子 类决定生产什么产品。
⑷ 抽象工厂(Abstract Factory)模式:提供一个创建产品族的接口,其每 个子类可以生产一系列相关的产品。
⑸ 建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分, 然后根据不同需要分别创建它们,最后构建成该复杂对象。
2、抽象工厂模式(Abstract Factory)
(1)模式的定义与特点
-
定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访 问类无需指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
-
满足条件:系统中有多个产品族,每个具体工厂创建同一族的但属于不同等级结构 的产品。系统一次只可能消费其中某一族产品,即同族的产品一起使用。
-
优点:可以在类的内部对产品族中相关联的多等级产品共同管理,增加一个新的产品族时不需要修改原 代码,满足开闭原则。
-
缺点:当产品族中需要增加一个新等级的产品时,则所有的工厂类都需要进行修改。
(2)模式的结构与实现
1、结构:
- 抽象工厂(Abstract Factory):提供了创建产品的接口,它包 含多个创建产品的方法newProduct(),可以创建多个不同等级的产品。
- 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个 抽象方法,完成具体产品的创建。
- 抽象产品(Product):定义了产品的规范,描述了产品的主要 特性和功能,抽象工厂模式有多个抽象产品。
- 具体产品(Concrete Product):实现了抽象产品角色所定义的 接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。
结构图:
2、实现:
例:用抽象工厂模 式设计农场类。
- 农场中除了像畜牧 场一样可以养动物,还可以 培养植物,如养马、养牛、 种菜、种水果等。
代码:
抽象工厂:农场类
//抽象工厂:农场类
interface Farm {
public Animal newAnimal();
public Plant newPlant();
}
具体工厂:韶关农场类
//具体工厂:韶关农场类
class SGfarm implements Farm
{
public Animal newAnimal()
{
System.out.println("新牛出生!");
return new Cattle();
}
public Plant newPlant()
{
System.out.println("蔬菜长成!");
return new Vegetables();
}
}
具体工厂:上饶农场类
//具体工厂:上饶农场类
class SRfarm implements Farm
{
public Animal newAnimal()
{
System.out.println("新马出生!");
return new Horse();
}
public Plant newPlant()
{
System.out.println("水果长成!");
return new Fruitage();
}
}
抽象产品:植物类
//抽象产品:植物类
interface Plant {
public void show();
}
具体产品:蔬菜类
//具体产品:蔬菜类
class Vegetables implements Plant
{
public Vegetables() {
}
// 重写父类的show方法,展示生产的产品
public void show()
{
System.out.println("产品:蔬菜");
}
}
具体产品:水果类
//具体产品:水果类
class Fruitage implements Plant
{
public Fruitage() {
}
// 重写父类的show方法,展示生产的产品
public void show()
{
System.out.println("产品:水果");
}
}
抽象产品:动物类
//抽象产品:动物类
interface Animal {
public void show();
}
具体产品:马类
//具体产品:马类
class Horse implements Animal
{
public Horse() {
}
// 重写父类的show方法,展示生产的产品
public void show()
{
System.out.println("产品:马");
}
}
具体产品:牛类
//具体产品:牛类
class Cattle implements Animal
{
public Cattle() {
}
// 重写父类的show方法,展示生产的产品
public void show()
{
System.out.println("产品:牛");
}
}
confg.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<className>SRfarm</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 FarmTest {
public static void main(String[] args) {
try
{
// 抽象工厂,农场
Farm f;
// 抽象产品:农场
Animal a;
// 抽象产品:植物
Plant p;
// 读取配置文件中的具体工厂
f=(Farm) ReadXML.getObject();
// 生产动物
a=f.newAnimal();
// 生产植物
p=f.newPlant();
// 展示
a.show();
p.show();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
(3)应用场景
- 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如:电器工厂中的电视机、洗衣机、空调等。
2)系统中有多个产品族,但每次只使用其中的某一族产品。如:有的粉丝只喜欢穿李宁牌的衣、裤和鞋。
3)系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。
(4)扩展
抽象工厂模式的扩展有一定的“开闭原则”倾斜性:
- 1)当增加一个新的产品族时只需增加一个新的具体工厂,不需
要修改原代码,满足开闭原则。 - 2)当产品族中需要增加一个新种类的产品时,则所有的工厂类
都需要进行修改,不满足开闭原则。 - 另一方面,当系统中只存在一个等级结构的产品时,抽象工厂模
式将退化到工厂方法模式。