4,单例模式
单例模式解释:
GoF对单例模式(Singleton Pattern)的定义是:保证一个类、只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。
单例模式是一种对象创建型模式,使用单例模式,可以保证为一个类只生成唯一的实例对象。也就是说,在整个程序空间中,该类只存在一个实例对象。
单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。
英文定义为:Ensure a class only has one instance, and provide a global point of access to it.
单例模式的UML图:
单例模式比较的单纯,其UML图如下所示:
单例模式深入分析:
单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。
单例模式适合于一个类只有一个实例的情况,比如窗口管理器,打印缓冲池和文件系统,它们都是原型的例子。典型的情况是,那些对象的类型被遍及一个软件系统的不同对象访问,因此需要一个全局的访问指针,这便是众所周知的单例模式的应用。当然这只有在你确信你不再需要任何多于一个的实例的情况下
在计算机系统中,需要管理的资源包括软件外部资源,譬如每台计算机可以有若干个打印机,但只能有一个Printer Spooler, 以避免两个打印作业同时输出到打印机中。每台计算机可以有若干传真卡,但是只应该有一个软件负责管理传真卡,以避免出现两份传真作业同时传到传真卡中的情况。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。
需要管理的资源也包括软件内部资源,譬如,大多数的软件都有一个(甚至多个)属性(properties)文件存放系统配置。这样的系统应当由一个对象来管理一个属性文件。
需要管理的软件内部资源也包括譬如负责记录网站来访人数的部件,记录软件系统内部事件、出错信息的部件,或是对系统的表现进行检查的部件等。这些部件都必须集中管理。
GG单例模式的第二个版本:“懒汉式”,在单线程下能够非常好的工作,但是在多线程下存在线程安全问题,具体代码如下:
1 package com.diermeng.designPattern.Singleton;
2 /*
3 * GG单例模式的第二个版本 采用“懒汉式” 在需要使用的时候才实例化GG
4 */
5 public class GGVersionTwo {
6 //GG的姓名
7 private String name;
8 //对单例本身引用的名称
9 private static GGVersionTwo gGVersionTwo;
10 public String getName() {
11 return name;
12 }
13 public void setName(String name) {
14 this.name = name;
15 }
16 //构造函数私有化
17 private GGVersionTwo() {
18 }
19 //提供一个全局的静态方法
20 public static GGVersionTwo getGG() {
21 if(gGVersionTwo == null) {
22 gGVersionTwo = new GGVersionTwo();
23 }
24 return gGVersionTwo;
25 }
26 }
GG单例模式第四个版本,既解决了“懒汉式的”多线程问题,又解决了资源浪费的现象,看上去是一种不错的选择,具体代码如下所示:
1 package com.diermeng.designPattern.Singleton;
2 /*
3 * GG单例模式的第四个版本,既解决了“懒汉式的”多线程问题,又解决了资源浪费的现象,看上去是一种不错的选择
4 */
5 public class GGVersionFour {
6 //GG的姓名
7 private String name;
8 //对单例本身引用的名称
9 private static GGVersionFour gGVersionFour;
10 public String getName() {
11 return name;
12 }
13 public void setName(String name) {
14 this.name = name;
15 }
16 //构造函数私有化
17 private GGVersionFour() {
18 }
19 //提供一个全局的静态方法
20 public static GGVersionFour getGG() {
21 if(gGVersionFour == null) {
22 synchronized (GGVersionFour.class) {
23 if(gGVersionFour == null) {
24 gGVersionFour = new GGVersionFour();
25 }
26 }
27 }
28 return gGVersionFour;
29 }
30 }
单例模式的优缺点分析:
优点:客户端使用单例模式类的实例的时候,只需要调用一个单一的方法即可生成一个唯一的实例,有利于节约资源。
缺点:首先单例模式很难实现序列化,这就导致采用单例模式的类很难被持久化,当然也很难通过网络传输;其次由于单例采用静态方法,无法在继承结构中使用。最后如果在分布式集群的环境中存在多个Java虚拟机的情况下,具体确定哪个单例在运行也是很困难的事情。
单例模式的实际应用简介:
单例模式一般会出现在以下情况下:
在多个线程之间,比如servlet环境,共享同一个资源或者操作同一个对象
在整个程序空间使用全局变量,共享资源
大规模系统中,为了性能的考虑,需要节省对象的创建时间等等。
温馨提示:
细心的读者可能会发现,笔者在写单例模式的双重检查方式的使用了“看上去是一种不错的选择”之语,之所以样说,是因为:Java的线程工作顺序是不确定的,这就会导致在多线程的情况没有实例化就使用的现象,进而导致程序崩溃。不过双重检查在C语言中并没有问题。因为大师说:双重检查对Java语言并不是成立的。尽管如此,双重检查仍然不失为解决多线程情况下单例模式的一种理想的方案。
5,原型模式
原文:http://www.cnblogs.com/guoshiandroid/archive/2010/07/03/1770357.html
原型模式应用场景举例:
GG和MM经常在QQ上聊天,但是GG打字的速度慢如蜗牛爬行,每次MM在瞬间完成恢复或者问候是,GG都会很紧张的去尽力快速打字,尽管如此,还是让MM有些不高心,MM说回复信息这么慢,显然是用心不专,不在乎她。哎,GG也是百口难辩啊,不过也确实是没有办法。
有一天,GG想自己的密友K倾诉了自己的苦衷。K顿生大笑。说道:“傻瓜,你怎么不去网上收集一些肉麻的情话以及一些你们经常说话会涉及到主题,把这些东西拷贝下来保存在自己的电脑或者U盘里面,这样一来如果下次在聊天就可以借用过来了!”,“K就是K,我怎么没有想到呢~妙极~妙极^_^”,“不过不要太高兴,这些东西是要适当修改的,要不然你把名字都搞错的话,就等着你的MM把你踹死吧O(∩_∩)O哈哈~”K补充道,“嗯,说的对,谢谢K哥解决了我的心腹之患啊”GG乐不可支的说道。
这是MM由在网上和GG聊天,GG专门复制那些实现准备好的肉麻情话经过稍加修改后发给MM,MM都快美死了…
原型模式解释:
原型模式(Prototype Pattern)是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用Prototype模式创建的实例,具有与原型一样的初始化数据
英文定义为:Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.
原型模式的UML图:
原型模式涉及以下的角色:
客户端(Client)角色: 客户端提出创建对象的请求。
抽象原型(Prototype)角色:通常由一个Java接口或者Java抽象类来实现。从而为具体原型设立好规范。
具体原型(Concrete Prototype)角色:被复制的具体对象,此具体角色实现了抽象原型角色所要求实现的方法。
原型模式的UML图如下所示:
原型模式深入分析:
原型模式的工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
Java在语言级别是直接支持原型模式的。我们知道,在java.lang.Object是一切类和接口的父类,而java.lang.Object正好提供了一个clone()方法来支持原型模式。当然,一个对象如果想具有被复制的能力,还必须声明自己实现了Cloneable接口,如果没有声明,就会在对象被复制的时候抛出CloneNotSupportedException.
在java.lang.Object中提供了一个 protected Object clone()方法来支持对象的克隆,子类可以采用默认的方式进行所有字段的复制,也可以在子类中覆盖clone()方便,根据实际需要定制自己的复制行为。
复制浅复制和深复制之分,浅复制是对基本数据类型和String类型而言的,深复制是对其他引用类型而言的。对于深复制,每一个应用也需要声明Cloneable接口。
原型模式使用场景分析及代码实现:
在上面的使用场景中,因为GG打字太慢经常被女朋友怪罪,所以有了拷贝网上肉麻情话的和主要聊天话题内容的办法。这样,以后GG每次和MM聊天的时候只需要把原话拷贝出来,加以适当修改就行,省时省力,而且效果绝佳^_^,这就是设计模式的原型模式的使用的好处O(∩_∩)O~
UML模型图如下所示:
建立一个肉麻情话类,类中有非常详细的注释,这里就不在解释了:
1 import java.util.ArrayList;
2 import java.util.List;
3 /*
4 * 肉麻情话类
5 */
6 public class SweetWord implements Cloneable{
7 //肉麻情话句子
8 private String content;
9 //肉麻情话句子集合
10 private List<String> contents;
11 /*
12 * 获取肉麻情话集合
13 */
14 public List<String> getContents() {
15 return contents;
16 }
17 /*
18 * 设置肉麻情话集合
19 */
20 public void setContents(List<String> contents) {
21 this.contents = contents;
22 }
23 /*
24 * 获取肉麻情话
25 */
26 public String getContent() {
27 return content;
28 }
29 /*
30 * 设置肉麻情话
31 */
32 public void setContent(String content) {
33 this.content = content;
34 }
35 /*
36 * 肉麻情话覆盖了Object类的clone()方法,因为这里有List引用进行深度复制
37 * @see java.lang.Object#clone()
38 */
39 public SweetWord clone() {
40 try {
41 //新建一个肉麻情话对象,同时复制基本的属性
42 SweetWord sweetWord = (SweetWord)super.clone();
43 //新建一个肉麻情话集合
44 List<String> newContents = new ArrayList<String>();
45 //把原对象的肉麻情话集合中的肉麻情话集合通过forEach循环加入新建的newContents中
46 for(String friend : this.getContents()) {
47 newContents.add(friend);
48 }
49 //把新的肉麻情话集合设置进新的对象
50 sweetWord.setContents(newContents);
51 //返回新的的肉麻情话对象
52 return sweetWord;
53 } catch (CloneNotSupportedException e) {
54 e.printStackTrace();
55 return null;
56 }
57 }
58 }
最后我们建立测试客户端:
import java.util.ArrayList;
import java.util.List;
import com.diermeng.designPattern.Prototype.impl.SweetWord;
/*
* 肉麻情话测试客户端
*/
public class PrototypeClient {
public static void main(String[] args) {
//新建一个肉麻情话对象并设置相应的属性
SweetWord content1 = new SweetWord();
List<String> contents = new ArrayList<String>();
contents.add("宝贝儿,我爱你");
contents.add("你是我的唯一");
content1.setContents(contents);
//复制content1
SweetWord content2 = content1.clone();
//分别输入两个对象的内容
System.out.println(content1.getContents());
System.out.println(content2.getContents());
//在原来的肉麻情话对象中加入新的内容并把新的内容设置进去
contents.add("你是我真命天女");
content1.setContents(contents);
//分别输出新的修改后的两个肉麻情话对象
System.out.println(content1.getContents());
System.out.println(content2.getContents());
}
}
输出的结果如下:
1 [宝贝儿,我爱你, 你是我的唯一]
3 [宝贝儿,我爱你, 你是我的唯一]
5 [宝贝儿,我爱你, 你是我的唯一, 你是我真命天女]
7 [宝贝儿,我爱你, 你是我的唯一]
原型模式的优缺点分析:
优点:
1.允许动态地增加或减少产品类。由于创建产品类实例的方法是产品类内部具有的,因此增加新产品对整个结构没有影响。
2.提供简化的创建结构。
3.具有给一个应用软件动态加载新功能的能力。
4.产品类不需要非得有任何事先确定的等级结构,因为原型模式适用于任何的等级结构。
缺点:
每一个类都必须配备一个克隆方法,这对于全新的类来说不是很难,而对已有的类来说实现clone()方法不一定很容易,而且在进行比较深层次的复制的时候也需要编写一定工作量的代码
原型模式的实际应用简介:
原型对象一般在适用于一下场景:
在创建对象的时候,我们不仅希望被创建的对象继承其类的基本机构,而且还希望继承原型对象的数据。
希望对目标对象的修改不影响既有的原型对象(深度克隆的时候可以完全互不影响)。
隐藏克隆操作的细节。很多时候,对对象本身的克隆需要涉及到类本身的数据细节。
温馨提示:
因为使用原型模式的时候每个类都要具备克隆方法。如果在类的设计之初没有很好的规划,等使用很久了才想到克隆,就可能非常的麻烦,尤其是在设计到深层次复制的时候,因为此时牵扯到很多因素,而且工作量非常大。
读Android之大话设计模式--18种设计模式(二):创建型设计模式,布布扣,bubuko.com
读Android之大话设计模式--18种设计模式(二):创建型设计模式
原文:http://www.cnblogs.com/wangziqiang/p/3582926.html