1 创建型模式
创建型主要关注类或者对象的创建过程,抽象了实例化过程。一个类创建型模式使用继承改变被实例化的类,而一个对象型模式将实例化委托另一个对象。
随着系统演化得越来越依赖对象复合而不是类继承,创建型模式变的更为重要。
1.1 工厂方法模式
1.1.1 意图
Factory Method : 定义一个创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。
1.1.2实用性
在下列情况下可以使用Factory Method模式:
• 当一个类不知道它所必须创建的对象的类的时候。
• 当一个类希望由它的子类来指定它所创建的对象的时候。
• 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
1.1.3结构
1.1.4参与者
• P r o d u c t
— 定义工厂方法所创建的对象的接口。
• C o n c r e t e P r o d u c t
— 实现P r o d u c t接口。
• C r e a t o r
— 声明工厂方法,该方法返回一个P r o d u c t类型的对象。C r e a t o r也可以定义一个工厂方法的缺省实现,它返回一个缺省的C o n c r e t e P r o d u c t对象。— 可以调用工厂方法以创建一个P r o d u c t对象。
• C o n c r e t e C r e a t o r
— 重定义工厂方法以返回一个C o n c r e t e P r o d u c t实例。
1.1.5代码示例
1. Product
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
*
抽象产品类
*/
public abstract class Product {
public abstract void doSomething();
}
2. ConcreteProduct1
public class ConcreteProduct1 extends Product {
public void doSomething() {
//
逻辑处理
}
}
3. Creator
public abstract class Creator {
/*
*
创建一个产品对象,其输入参数类型可以自行设置
*
通常为String、Enum、Class等,当然也可以为空
*/
public abstract <T extends Product> T createProduct(Class<T> c);
}
4. ConcreteCreator
public class ConcreteCreator extends Creator {
public <T extends Product> T createProduct(Class<T> c){
Product product=null;
try {
product = (Product)Class.forName(c.getName()).newInstance();
} catch (Exception e) {
//
异常处理
}
return (T)product;
}
}
1.2 抽象工厂模式
1.2.1 意图
Abstract Factory: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定具体的类。
1.2.2实用性
在以下情况可以使用Abstract Factory模式
• 一个系统要独立于它的产品的创建、组合和表示时。
• 一个系统要由多个产品系列中的一个来配置时。
• 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
• 当你提供一个产品类库,而只想显示它们的接口而不是实现时。
1.2.3结构
1.2.4优缺点
抽象工厂模式的最大缺点就是产品族扩展非常困难,要修改最上面AbstractFactory,违反开闭原则。但是该模式产品的扩展很容易。
1.2.5参与者
• A b s t r a c t F a c t o r y
— 声明一个创建抽象产品对象的操作接口。
• C o n c r e t e F a c t o r y
— 实现创建具体产品对象的操作。
• A b s t r a c t P r o d u c t
— 为一类产品对象声明一个接口。
• C o n c r e t e P r o d u c t
— 定义一个将被相应的具体工厂创建的产品对象。
— 实现A b s t r a c t P r o d u c t接口。
• C l i e n t
— 仅使用由A b s t r a c t F a c t o r y和A b s t r a c t P r o d u c t类声明的接口。
1.2.6代码示例
1. AbstractCreator
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
*
抽象的产品类
*/
public abstract class AbstractCreator {
public abstract AbstractProductA createProductA();
}
2.
Creator
public class Creator1 extends AbstractCreator {
//
只生产产品等级为1的A产品
public AbstractProductA createProductA() {
return new ProductA1();
}
}
3.
AbstractProductA
public abstract class AbstractProductA {
//
每个产品相同方法,不同实现
public abstract void doSomething();
}
4.
ProductA
public class ProductA1 extends AbstractProductA {
@Override
public void doSomething() {
System.out.println("
产品A1的实现方法");
}
}
5.
Client
public class Client {
public static void main(String[] args) {
//
定义出两个工厂
AbstractCreator creator1 = new Creator1();
}
}
1.3 建造者模式
1.3.1 意图
Builder: 将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。
1.3.2实用性
在以下情况使用B u i l d e r模式
• 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
• 当构造过程必须允许被构造的对象有不同的表示时。
1.3.3结构
1.3.4优缺点
建造者模式优点是封装性,控制细节风险。
1.3.5参与者
• B u i l d e r
— 为创建一个P r o d u c t对象的各个部件指定抽象接口。
• C o n c r e t e B u i l d e r
— 实现B u i l d e r的接口以构造和装配该产品的各个部件。
— 定义并明确它所创建的表示。
— 提供一个检索产品的接口
• Director
— 构造一个使用B u i l d e r接口的对象。
• P r o d u c t
— 表示被构造的复杂对象。C o n c r e t e B u i l d e r创建该产品的内部表示并定义
1.3.6代码示例
1. Builder
public abstract class Builder {
//
设置产品的不同部分,以获得不同的产品
public abstract void setPart();
//
建造产品
public abstract Product buildProduct();
}
2.
ConcreteBuilder
public class ConcreteBuilder extends Builder {
private Product product = new Product();
//
设置产品零件
public void setPart(){
/*
*
产品类内的逻辑处理
*/
}
//
组建一个产品
public Product buildProduct() {
return product;
}
}
3.
Director
public class Director {
private Builder builder = new ConcreteProduct();
//
构建不同的产品
public Product getAProduct(){
builder.setPart();
/*
*
设置不同的零件,产生不同的产品
*/
return builder.buildProduct();
}
}
4.
Product
public class Product {
public void doSomething(){
//
独立业务处理
}
1.4 原型模式
1.4.1 意图
Prototype: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
1.4.2实用性
当一个系统应该独立于它的产品创建、构成和表示时,要使用P r o t o t y p e模式;以及
• 当要实例化的类是在运行时刻指定时,例如,通过动态装载;或者
• 为了避免创建一个与产品类层次平行的工厂类层次时;或者
• 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们
可能比每次用合适的状态手工实例化该类更方便一些。
1.4.3结构
1.4.4优缺点
原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量对象,但是直接在内存拷贝,构造函数不会执行的。
1.4.5注意点
原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量对象,但是直接在内存拷贝,构造函数不会执行的。
1. 构造函数不会执行
2. 留意深拷贝和浅拷贝
3. 与 final关键字冲突
1.4.6参与者
• P r o t o t y p e
— 声明一个克隆自身的接口。
• C o n c r e t e P r o t o t y p e
— 实现一个克隆自身的操作。
• C l i e n t
— 让一个原型克隆自身从而创建一个新的对象。
1. Thing
public class Thing implements Cloneable{
//
定义一个私有变量
private ArrayList<String> arrayList = new ArrayList<String>();
@Override
public Thing clone(){
Thing thing=null;
try {
thing = (Thing)super.clone();
this.arrayList = (ArrayList<String>)this.arrayList.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return thing;
}
//
设置HashMap的值
public void setValue(String value){
this.arrayList.add(value);
}
//
取得arrayList的值
public ArrayList<String> getValue(){
return this.arrayList;
}
}
2.
Client
public class Client {
public static void main(String[] args) {
//
产生一个对象
Thing thing = new Thing();
//
设置一个值
thing.setValue("
张三");
thing.setValue("abcd");
//
拷贝一个对象
Thing cloneThing = thing.clone();
cloneThing.setValue("
李四");
System.out.println(thing.getValue());
}
}
1.5 单例模式
1.5.1 意图
Singleton: 保证一个类仅有一个实例,并提供一个访问它的全局访问点。
1.5.2适用性
在下面的情况下可以使用S i n g l e t o n模式
• 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
• 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
1.5.3结构
1.5.4注意点
1)java中对象默认是不可以被复制的,但如果实现了cloneable接口,实现了clone方法,
则可以直接创建一个新对象,即使构造器是私有的。
2)单例对象如果在内存中长久不使用,有可能会被JVM回收。如果当做计数器使用,则会
出现问题。解决方法如下:
由容器管理单例的生命周期,如java ee容器或者spring,可以让对象长久贮存。
通过异步记录的方式,观察者模式同步记录。
java 中创建对象的方法
1、通过new 生成对象,私有构造方法则不允许。
2、运用反射手段,调用java.lang.Class 或者 java.lang.reflect.Constructor 类的newInstance()实例方法
Class类的newInstance方法
CreateInstance instance = CreateInstance.class.newInstance();
或者使用下面的语句(只需要存在相应的.class文件即可)
CreateInstance instance = (CreateInstance)Class.forname("com.create.instance.CreateInstance").newInstance();
注意 :newInstance创建对象实例的时候会调用无参的构造函数,所以必需确保类中有无参数的构造函数,
否则将会抛出java.lang.InstantiationException异常。
3、调用对象的clone()方法
clone 必须实现cloneable接口,实现clone方法。直接在内存中拷贝,不执行构造函数。
super.clone();
浅拷贝:
Object类提供的clone方法只是拷贝本对象,内部数组引用不拷贝,还是指向原对象的内存地址。(不安全)
深拷贝:
obj = super.clone();
obj.xxxx = this.xxx.clone();
4、运用序列化手段,调用ObjectInputStream的readObject方法。
如果对象是通过ObjectInputStream类的readObject()方法创建的,那么Java虚拟机通过从输入流中读入的序列化数
1.5.5参与者
• S i n g l e t o n
— 定义一个I n s t a n c e操作,允许客户访问它的唯一实例。I n s t a n c e是一个类操作。
— 可能负责创建它自己的唯一实例。
1. Singleton
public final class Singleton {
private static Singleton singleton = null;
//
限制产生多个对象
private Singleton(){
}
//
通过该方法获得实例对象
public synchronized static Singleton getSingleton(){
if(singleton == null){
singleton = new Singleton();
}
return singleton;
}
1.6 创建类模式的讨论
创建类模式主要能够提供对象的创建和管理职责。
1.6.1工厂方法模式与建造者模式
工厂方法模式注重的是整体对象的创建方法,而建造者模式注重的是部件构建的过程,旨在通过一步一步的精确构造创建一个复杂的对象。他们之间的区别也是比较明显的。
l 意图不同
工厂方法模式里,关注的是产品整体,不需要关注细节;但在建造者模式中,关注的是“由零件一步一步组装出产品对象”。
l 复杂度不同
工厂方法模式创建的一般都是单一的产品;而建造者模式创建的则是一个符合产品,它由各个部件复合而成,一般来说工厂方法模式的对象粒度比较粗,而建造者模式粒度比较细。
1.6.2抽象工厂模式与建造者模式
抽象工厂模式实现对产品家族的创建,一个产品家族是一系列产品:具有不同分类维度的产品组合,而不需要关心构建的过程。建造者模式要求按照指定的蓝图建造产品。
相比来说,抽象工厂模式比建造者模式的尺度要大,它关注产品整体,而建造者模式关注构建过程,因此建造者更容易构建一个新的产品。