创建型模式的特点和分类
关注点
怎样创建对象?主要特点就是"将对象的创建与使用分离",降低系统耦合性,不关注对象创建的细节。对象创建由工厂来完成。就像商品购物, 无需关心生产
创建型模式:
- 单例模式 (Singleton) 生成一个对象,提供全局访问点
- 原型模式(Prototype) 将一个对象作为原型,通过复制或克隆多个和原型类似的新实例
- 工厂方法模式(FactoryMethod) 定义一个创建产品的接口,由子类决定生产什么产品
- 抽象工厂模式(AbstractFactory)提供创建产品族的,每个子类可以生产一系列的相关产品
- 建造者模式(Builder) 将一个复杂的对象分解成多个相对简单的部分,根据需要创建,最后构建复杂的对象
除了工厂方法模式属于类创建模式, 其他的都属于对象创建型模式
单例模式
节省内存资源,保证数据一致性, 某些类只能创建一个实例,这就是所谓的单例模式
单例模式的定义和特点
一个类只有一个实例,且该类能自行创建这个实例的一种模式
- 单例类只有一个实例对象
- 单例对象必须要由单例类来创建
- 单例类对外提供一个访问该单例的全局访问点
单例模式的结构和实现
- 单例模式的结构
主要角色
- 单例类:包含一个实例且能自行创建这个实例的类
- 访问类:使用单例的类
单例模式的实现
有八种方式,建议使用静态内部类方式和枚举方式
应用场景
- 某类只要求生成一个对象。 如一个班的班长,每个人的身份证号
- 当对象需要被共享的场合。如配置对象, 数据库连接池等。
- 当类需要频繁创建和销毁的时候。 如多线程连接池,网络连接池等。
扩展
单例模式可以扩展为有限的多例模式,这种模式可以生成有限的对象保存在arraylist中,客户随机获取
原型模式
定义和特点
用一个已经创建的对象做为原型,通过复制该对象来创建一个和原型相同或相似的新对象。这种方式创建对象高效
结构和实现
java提供clone()的方法,实现原型模式很简单
- 模式的结构
- 抽象原型类:规定了原型对象必须要实现的接口
- 具体原型类:实现抽象原型类的clone()方法,它是可被复制的对象
- 访问类:使用具体原型类中的clone()方法来复制新的对象
- 模式的实现
- 浅克隆
java中提供的浅克隆clone()方法,具体的原型类只要实现了Cloneable接口就可实现对象的浅克隆,这里的Cloneable接口就是抽象原型类。
//具体原型类
class Realizetype implements Cloneable
{
Realizetype()
{
System.out.println("具体原型创建成功!");
}
public Object clone() throws CloneNotSupportedException
{
System.out.println("具体原型复制成功!");
return (Realizetype)super.clone();
}
}
//原型模式的测试类
public class PrototypeTest
{
public static void main(String[] args)throws CloneNotSupportedException
{
Realizetype obj1=new Realizetype();
Realizetype obj2=(Realizetype)obj1.clone();
System.out.println("obj1==obj2?"+(obj1==obj2));
}
}
- 深克隆
应用实例
- 复制自己
- 相似对象的复制 (复制自己,修改部分属性)
应用场景
- 对象之间相同或相似,只有个别属性不同
- 对象创建过程比较麻烦,但复制简单
扩展
可以扩展为带原型管理器的原型模式,在原型模式上增加一个原型管理器类(PrototypeManager),用HashMap保存多个复制原型,通过get(id)方法获取复制的原型。
工厂方法模式
定义和特点
定义一个创建产品对象的工厂接口,将产品对象实际创建工作推迟具体子工厂类当中。满足"创建和使用分离"的特点
被创建对象的成为"产品",创建产品的对象成为"工厂"。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫做"简单工厂模式",不属于23种经典设计模式,缺点就是增加新产品的时候, 会违背"开闭原则"
工厂方法模式是对简单工厂模式进一步抽象化,满足开闭原则
优点:
- 用户只需要知道工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
- 系统增加新产品的时候,只需要增加具体的产品类和对应的具体工厂类,满足开闭原则
缺点:
- 增加一个产品的时候,要增加具体的产品类和一个对应的具体工厂类,增加了系统的复杂度
结构和实现
主要角色
- 抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法newProduct()来创建产品
- 具体工厂:主要实现抽象工厂的抽象方法,完成具体产品的创建
- 抽象产品:定义产品的规范,描述了产品的主要特性和功能
- 具体产品:实现了抽象产品定义的接口,由具体工厂来创建同具体工厂一一对应
模式的实现
package FactoryMethod;
public class AbstractFactoryTest
{
public static void main(String[] args)
{
try
{
Product a;
AbstractFactory af;
af=(AbstractFactory) ReadXML1.getObject();
a=af.newProduct();
a.show();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
//抽象产品:提供了产品的接口
interface Product
{
public void show();
}
//具体产品1:实现抽象产品中的抽象方法
class ConcreteProduct1 implements Product
{
public void show()
{
System.out.println("具体产品1显示...");
}
}
//具体产品2:实现抽象产品中的抽象方法
class ConcreteProduct2 implements Product
{
public void show()
{
System.out.println("具体产品2显示...");
}
}
//抽象工厂:提供了厂品的生成方法
interface AbstractFactory
{
public Product newProduct();
}
//具体工厂1:实现了厂品的生成方法
class ConcreteFactory1 implements AbstractFactory
{
public Product newProduct()
{
System.out.println("具体工厂1生成-->具体产品1...");
return new ConcreteProduct1();
}
}
//具体工厂2:实现了厂品的生成方法
class ConcreteFactory2 implements AbstractFactory
{
public Product newProduct()
{
System.out.println("具体工厂2生成-->具体产品2...");
return new ConcreteProduct2();
}
}
package FactoryMethod;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
class ReadXML1
{
//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
public static Object getObject()
{
try
{
//创建文档对象
DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=dFactory.newDocumentBuilder();
Document doc;
doc=builder.parse(new File("src/FactoryMethod/config1.xml"));
//获取包含类名的文本节点
NodeList nl=doc.getElementsByTagName("className");
Node classNode=nl.item(0).getFirstChild();
String cName="FactoryMethod."+classNode.getNodeValue();
//System.out.println("新类名:"+cName);
//通过类名生成实例对象并将其返回
Class<?> c=Class.forName(cName);
Object obj=c.newInstance();
return obj;
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
}
}
Config1.xmln内容
<?xml version="1.0" encoding="UTF-8"?>
<config>
<className>ConcreteFactory1</className>
</config>
应用场景
- 客户只知道创建产品的工厂名,而不知道具体产品名
- 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口
- 客户不关心创建产品的细节,只关心产品的品牌
扩展
当需要生成的产品不多且不会增加,一个具体的工厂类就可以完成任务时,可删除抽象工厂类,这是工厂方法模式退化成简单工厂模式。