前面两篇文章中讨Z下创建型设计模式的工厂模式、抽象工厂模式、单例模式,今天ql聊一聊创建型模式的剩下两U,Builder模式和Prototype模式?/p>
1、Builder模式
何ؓBuilder模式Q其实Builder模式比较好理解,是一个复杂对象的创徏q程分解成几个Step,而每个step又抽象出来。具体实现由每个子类自己来决定,在通过W三方的一个DriectorcL实现l合Step的顺序以辑ֈ最l的创徏q个复杂的对象?/p>
具体可以见如下的图(from wikiQ:
从图中,我们可以看到Director的Constructcȝ于将每个step构徏hQBuilder中的buildPart()具体抽象了创建的q程q承类ConcreteBuilder的BuilderPart()来实现具体的构徏。最l构Z个完整的Product?/p>
后面在聊一下结合其他设计模式的理解Q关于Builder和Abstract Factory。Builder主要是构造整理里面的每一个part。而Abstract Factory则是Z为统一cȝProduct提够工厂。还有关于Build PartQ个人倒是觉得可以l合工厂模式来做Q这样将每个part的实现由和ConcreteBuilder解耦合了,例如通过注入的方式来表明具体的实现?/p>
H然惛_Q如果能把各U设计模式用的游刃有余那该是多么happy的一件事啊?/p>
2、Prototype模式
和builder模式一PPrototype也同样非常好理解Q你可能l常不经意间qC它。例如你已经有一个某个类的对象了Q现在你需要创Z个和本对象相同的新对象。(h意理解这里相同的意思哦Q那该如何呢Q基本上׃惛_Clone()Ҏ了。没错,clone()Ҏ是原型模式的实现。下面先看一下原型模式的l构图(from 大话设计模式Q?/p>
在原型模式中一般会要处理的是深浅拯的问题,其实关于深浅拯也是比较好理解的。以javaZQjava的内存分为四快:堆、栈、代码区、数据区。对象的引用攑֜栈,对象攑֜堆。对于clone()毫无疑问Q会重新开辟一个堆I间构徏新对象。对于该对象的基本类型复制ؓ原对象的倹{那么对于类cd呢?有两U方式:一U是同样开辟一个空间存放该cȝ型(注意q是一个递归的过E)Q这是所谓的深拷贝;q有一U则是只是引用指向原对象cȝ型的实例Q此为浅拯?/p>
关于深拷贝一定要注意是Q这是一个递归的过E。你必须保此cL包含的所有类Q包括递归包含Q,都实C深拷贝。还有就是要求父cd象也实现对象也实Cclone()ҎQƈ完成深拷贝。而且在子cȝclone()中调用super.clone()Ҏ?/p>
Ps:在java中一般实现Cloneable接口中的clone()Ҏ卛_?br />pdf下蝲Q?a href="/Files/zhenxuanpan/设计模式之Builder模式和Prototype模式.pdf">/Files/zhenxuanpan/设计模式之Builder模式和Prototype模式.pdf
如果说道设计模式Q我惛_家想到最多的应该是单例模式和工厂模式,上一文章中详细介绍了工厂模式以及简单工厂模式和抽象工厂模式。相对工厂模式,单例模式要简单一点,但是单例模式也同h很多值得思考的问题Q下面就来看一下这些问题以及解决的办法?/p>
1、静态初始化实例对象Q网上也有h叫饥饿实例化Q?/p>
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {
}
public static EagerSingleton getInstance() {
return EagerSingleton.instance;
}
}
2、当W一ơ需要的时候创建实例化对象Q懒汉实例化Q?/p>
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton() {
}
public synchronized static LazySingleton getInstance() {
if(instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
q里一定要注意加synchronized,否则׃引进多线E下的不安全的情况了?/p>
但是Q考虑到synchronized加在Ҏ上,锁的_度太多Q会Ҏ能产生影响。所以引入下面的dcl法q行改进?/p>
3、采用dcl法改进2Q关于dclLq个http://en.wikipedia.org/wiki/Double-checked_lockingQ后面找旉详细聊聊q个东西Q貌似是jee中一个很常用的东西)
public class DclLazySingleton {
private static DclLazySingleton instance = null;
private DclLazySingleton() {
}
public static DclLazySingleton getInstance() {
if(instance == null) {
synchronized(DclLazySingleton.class) {
if(instance == null) {
instance = new DclLazySingleton();
}
}
}
return instance;
}
}
ps:按照wiki的说法,q种法是有问题Q这个后面在讨论Q不q貌似异常出现的概率很小Q而且很多成功的开源项目都用到了它Q所以,不用担心Q?/p>
4、看到这里,是不是大家觉得单例模式就该解决了呢?可是有没有发C个问题呢Q上面的单例c都不能做父c,因ؓ构造方法是U有的,psQ子cȝ构造方法默认会去调用父cȝ构造方法,如果是私有的Q这个果断没法承啊?/p>
所以就引进了下面的注册式的单例实现方式。看|上很多人都说spring中用了q种方式Q所以开始了解这U方式,其实l典的GoF的书中就有对q个的介l?/p>
public class RegisterSingleton {
private static Map<String, RegisterSingleton> instanceMap = new HashMap<String, RegisterSingleton>();
static {
RegisterSingleton instanceThis = new RegisterSingleton();
instanceMap.put(RegisterSingleton.class.getName(), instanceThis);
}
protected RegisterSingleton() {
}
public static RegisterSingleton getInstance(String name) {
if(name == null) {
name = RegisterSingleton.class.getName();
}
if(instanceMap.get(name) == null) {
try {
instanceMap.put(name, (RegisterSingleton)Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return instanceMap.get(name);
}
public static RegisterSingleton getInstance() {
return getInstance(RegisterSingleton.class.getName());
}
}
使用重蝲来便L调用getInstance()Ҏ?/p>
子类如果l承去调用getInstanceҎ呢?L如下代码Q?/p>
public class RegisterSingletonChild extends RegisterSingleton {
protected RegisterSingletonChild() {}
public static RegisterSingletonChild getInstance() {
return (RegisterSingletonChild)RegisterSingleton.getInstance(RegisterSingletonChild.class.getName());
}
}
当然Q如果子cȝ定没有子cȝ话,则可以考虑用privateL代protected.
5、ȝ
以上4U方式基本包含了单例模式使用的四U方法,考虑了多U程下单例模式的U程安全性和有承情况下的注册式单例实现?br />老规矩上pdf,呵呵?a href="/Files/zhenxuanpan/设计模式之单例模式的详解.pdf">/Files/zhenxuanpan/设计模式之单例模式的详解.pdf
在设计模式中的创模式中有三中模式可以说是同根同源。它们就是简单工厂模式、工厂模式、抽象工厂模式。下面我们逐一看它们的特点以及异同?/p>
1、简单工厂模?/p>
单工厂模式ƈ不在GoF?3U设计模式之列,不过它却是工厂模式和抽象工厂模式最化的一U表现Ş式。它通过一个工厂类Factory来根据传入的参数军_构徏具体哪一cM品的实例。它屏蔽了客L创徏具体产品实例的过E,提供l客L可用的对象。但是它有一个致命的~点是Factory中的逻辑比较负责Q要Ҏ参数d断生成怎么L产品实例l客L。特别是产品实例动态的增加的时候,你必要修改Factory的判断逻辑Q这一点违背了“开-闭原?#8221;。可能这也是它未能入?3U设计模式的原因吧?/p>
上uml囑Q这h易于理解Q图来源于百度百U)
2、工厂模?/p>
如果说什么模式应用最多,个h认ؓ是工厂模式了。例如想Spring中Factory,Bean实在是太常见了。你自己qx写程序,new一个对象也是非常常见的Q所以工厂模式常见也是非常正常。如果要说工厂模式和抽象工厂模式的区别,那就要先看抽象工厂的~点了,q背?#8220;开-?#8221;原则。所以工厂模式,׃Z改进Q每一个Product都有一个自己对应的工厂。当然这些工厂都l承于抽象工厂类Qƈ实现了工厂方法?/p>
上uml囑Q自己可以对比一下,囄来源于大话设计模?/p>
3、抽象工厂模?/p>
看了上面的工厂模式,你是不是会觉得很爽,因ؓ大部分new出来的对象都可以用工厂去产生Q确实,在Spring中,所有的cL员变量都是配|文仉q去的,也就是通过工厂产生的。但是你会发C个问题,如果是一个工厂只产生一个beanQ那么如果我想生一lbean怎么办呢Q因为很多时候某一lbean是捆l在一L。例如db中,sqlServer,mysql,oracle各自对应一lConnection, resultSet{,那是你这个时候就需要抽象工厂了Q它提供了这样对一lor一cbean区分的需求的支持?/p>
上uml囑Q偶觉得有图有真相,呵呵。图片仍旧来自大话设计模式?br />
4、ȝ
通过上面的介l和图例Q基本可以看ZU工厂模式的特点和异同。主要是它们的不同点Q简单工厂封装了构徏对象的过E,但内部存在判断逻辑Q所以违背了“开-?#8221;原则。工厂模式通过Ҏ一个product增加一个工厂去增加弥补q个~点。但是工厂模式又不能生成同一cd的多个productQ所以抽象工厂模式通过增加多个工厂Ҏ去解册个问题?br />最后附上文的pdf吧。呵呵,希望对设计模式初学者有用?br />/Files/zhenxuanpan/设计模式之三U工?pdf