??xml version="1.0" encoding="utf-8" standalone="yes"?> 一、引?br />
话说十年前,有一个爆发户Q他家有三辆汽RQ?span style="font-size: 10pt">BenzQ奔驎ͼ?span style="font-size: 10pt">BmwQ宝马)?span style="font-size: 10pt">Audi //具体产品角色 public class Bmw implements Car{ //工厂c角?span style="font-size: 10pt"> //工厂Ҏ //判断逻辑Q返回具体的产品角色l?span style="font-size: 10pt">Client ...... 四、工厂方法模?span style="font-size: 10pt"> 我们q是老规矩用一个完整的例子来看看工厂模式各个角色之间是如何来协调的。话说暴发户生意做大Q自qpR也越来越多。这可苦了那位司机师傅了Q什么R它都要记得,l护Q都要经q他来用!于是暴发户同情他_看你跟我q么多年的䆾上,以后你不用这么辛苦了Q我l你分配几个人手Q你只管好他们p了!于是Q工厂方法模式的理出现了。代码如下: Car car = driver.driverCar(); 五、小l?span style="font-size: 10pt"> 六、抽象工厂模?span style="font-size: 10pt"> 图中?span style="font-size: 10pt">BmwCar?span style="font-size: 10pt">BenzCar是两个产品树(产品层次l构Q;而如图所C的BenzSportsCar?span style="font-size: 10pt">BmwSportsCar是一个品族。他们都可以攑ֈ跑R家族中,因此功能有所兌。同?span style="font-size: 10pt">BmwBussinessCar?span style="font-size: 10pt">BenzSportsCar也是一个品族?span style="font-size: 10pt"> 看过了前两个模式Q对q个模式各个角色之间的协调情况应该心里有个数了,我就不D具体的例子了。只是一定要注意满使用抽象工厂模式的条件哦Q不然即使存在了多个产品树,也存在品族Q但是不能用的?/span>
java工厂模式
工厂模式主要是ؓ创徏对象提供了接口。工厂模式按照?span style="font-size: 10pt">Java与模式》中的提法分Zc:
1. 单工厂模?span style="font-size: 10pt">(Simple Factory)
2. 工厂Ҏ模式(Factory Method)
3. 抽象工厂模式(Abstract Factory)
q三U模式从上到下逐步抽象Qƈ且更具一般性。还有一U分cLQ就是将单工厂模式看为工厂方法模式的一U特例,两个归ؓ一cR下面是使用工厂模式的两U情况:
1.在编码时不能预见需要创建哪U类的实例?span style="font-size: 10pt">
2.pȝ不应依赖于品类实例如何被创建、组合和表达的细?/span>
思义Q这个模式本w很单,而且使用在业务较单的情况下?span style="font-size: 10pt">
它由三种角色l成Q关p见下面的类图)Q?span style="font-size: 10pt">
1、工厂类角色Q这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往׃个具体类实现?/span>
那么单工厂模式怎么用呢Q我来D个例子吧Q我惌个比讲一大段理论上的文字描述要容易理解的多!下面来l那个暴发户ȝ: P
在用了单工厂模式后Q现在暴发户只需要坐在R里对司机说句Q?span style="font-size: 10pt">"开?span style="font-size: 10pt">"可以了。来看看怎么实现的:
//抽象产品角色
public interface Car{
public void drive();
}
public class Benz implements Car{
public void drive() {
System.out.println("Driving Benz ");
}
}
public void drive() {
System.out.println("Driving Bmw ");
}
}
。。。(奥_我就不写?span style="font-size: 10pt">:PQ?/span>
public class Driver{
//注意 q回cd为抽象品角?span style="font-size: 10pt">
public static Car driverCar(String s)throws Exception {
if(s.equalsIgnoreCase("Benz")) return new Benz();
else if(s.equalsIgnoreCase("Bmw"))
return new Bmw();
else throw new Exception();
。。?/span>
public class Magnate{
public static void main(String[] args){
try{
//告诉司机我今天坐奔驰
Car car = Driver.driverCar("benz");
//下命令:开?span style="font-size: 10pt">
car.drive();
。。?span style="font-size: 10pt">
如果所有的cL在一个文件中Q请不要忘记只能有一个类被声明ؓpublic?/span> E序中类之间的关pd下:
下面我们从开闭原则上来分析下单工厂模式。当暴发户增加了一辆R的时候,只要W合抽象产品制定的合同,那么只要通知工厂cȝ道就可以被客户用了。那么对于品部分来_它是W合开闭原则的--Ҏ展开放、对修改关闭Q但是工厂部分好像不太理惻I因ؓ每增加一辆RQ都要在工厂cM增加相应的商业逻辑和判断逻辑Q这显自然是q背开闭原则的?span style="font-size: 10pt">
对于q样的工厂类Q在我们的例子中是ؓ司机师傅Q,我们U它为全能类或者上帝类?span style="font-size: 10pt">
我们丄例子是最单的情况Q而在实际应用中,很可能品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些品,所以这可能会把我们的上帝类坏了Q进而篏坏了我们可爱的程序员:(
正如我前面提到的单工厂模式适用于业务将单的情况下。而对于复杂的业务环境可能不太适应ѝ这应该由工厂Ҏ模式来出ZQ!
先来看下它的l成吧:
1、抽象工厂角Ԍq是工厂Ҏ模式的核心,它与应用E序无关。是具体工厂角色必须实现的接口或者必ȝ承的父类。在java中它由抽象类或者接口来实现?span style="font-size: 10pt">
2、具体工厂角Ԍ它含有和具体业务逻辑有关的代码。由应用E序调用以创建对应的具体产品的对象。在java中它由具体的cL实现?span style="font-size: 10pt">
3、抽象品角Ԍ它是具体产品l承的父cL者是实现的接口。在java中一般有抽象cL者接口来实现?span style="font-size: 10pt">
4、具体品角Ԍ具体工厂角色所创徏的对象就是此角色的实例。在java中由具体的类来实现?span style="font-size: 10pt">
来用cd来清晰的表示下的它们之间的关p:
//抽象产品角色Q具体品角色与单工厂模式类|只是变得复杂了些Q这里略?span style="font-size: 10pt">
//抽象工厂角色
public interface Driver{
public Car driverCar();
}
public class BenzDriver implements Driver{
public Car driverCar(){
return new Benz();
}
}
public class BmwDriver implements Driver{
public Car driverCar() {
return new Bmw();
}
}
......//应该和具体品Ş成对应关p,q里?span style="font-size: 10pt">...
//有请暴发户先?span style="font-size: 10pt">
public class Magnate
{
public static void main(String[] args)
{
try{
Driver driver = new BenzDriver();
car.drive();
}catch(Exception e)
{ }
}
}
工厂Ҏ使用一个抽象工厂角色作为核心来代替在简单工厂模式中使用具体cM为核心。让我们来看看工厂方法模式给我们带来了什么?使用开闭原则来分析下工厂方法模式。当有新的品(x发户的汽车)产生Ӟ只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么可以被客户使用Q而不必去修改M已有的代码。看来,工厂Ҏ模式是完全符合开闭原则的Q?span style="font-size: 10pt">
使用工厂Ҏ模式以应付我们可能遇到的大部分业务需求。但是当产品U类非常多时Q就会出现大量的与之对应的工厂类Q这不应该是我们所希望的。所以我在这U情况下使用单工厂模式与工厂Ҏ模式相结合的方式来减工厂类Q即对于产品树上cM的种c(一般是树的叶子中互为兄弟的Q用简单工厂模式来实现?span style="font-size: 10pt">
当然Ҏ的情况,pҎ对待了:对于pȝ中存在不同的产品树,而且产品树上存在产品族,那么q种情况下就可能可以使用抽象工厂模式了?/span>
让我们来看看单工厂模式、工厂方法模式给我们的启q:
如果不用工厂模式来实现我们的例子,也许代码会减很?span style="font-size: 10pt">--只需要实现已有的车,不用多态。但是在可维护性上Q可扩展性上是非常差的(你可以想象一下,d一辆R后要牵动的类Q。因此ؓ了提高扩展性和l护性,多写些代码是值得的?/span>
先来认识下什么是产品族:位于不同产品{l构中,功能相关联的产品l成的家族。如果光看这句话p清楚的理解这个概念,我不得不佩服你啊。还是让我们用一个例子来形象地说明一下吧?/span>
回到抽象产品模式的话题上Q可以这么说Q它和工厂方法模式的区别在于需要创建对象的复杂E度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。抽象工厂模式的用意为:l客L提供一个接口,可以创徏多个产品族中的品对象。而且使用抽象工厂模式q要满一下条Ӟ
1.pȝ中有多个产品族,而系l一ơ只可能消费其中一族?span style="font-size: 10pt">
2.同属于同一个品族的品以其用?span style="font-size: 10pt">
来看看抽象工厂模式的各个角色Q和工厂Ҏ的如Z辙)Q?span style="font-size: 10pt">
抽象工厂角色Q这是工厂方法模式的核心Q它与应用程序无兟뀂是具体工厂角色必须实现的接口或者必ȝ承的父类。在java中它由抽象类或者接口来实现?span style="font-size: 10pt">
具体工厂角色Q它含有和具体业务逻辑有关的代码。由应用E序调用以创建对应的具体产品的对象。在java中它由具体的cL实现?span style="font-size: 10pt">
抽象产品角色Q它是具体品承的父类或者是实现的接口。在java中一般有抽象cL者接口来实现?span style="font-size: 10pt">
具体产品角色Q具体工厂角色所创徏的对象就是此角色的实例。在java中由具体的类来实现?span style="font-size: 10pt">
]]>
Singleton模式主要作用是保证在Java应用E序中,一个类Class只有一个实例存在?
在很多操作中Q比如徏立目?数据库连接都需要这L单线E操作?/p>
q有, singleton能够被状态化; q样Q多个单态类在一起就可以作ؓ一个状态仓库一样向外提供服务,比如Q你要论坛中的帖子计数器Q每ơ浏览一ơ需要计敎ͼ单态类能否保持住这个计敎ͼq且能synchronize的安全自动加1Q如果你要把q个数字怹保存到数据库Q你可以在不修改单态接口的情况下方便的做到?/p>
另外斚wQSingleton也能够被无状态化。提供工h质的功能,
Singleton模式׃ؓ我们提供了这样实现的可能。用Singleton的好处还在于可以节省内存Q因为它限制了实例的个数Q有利于Java垃圾回收Qgarbage collectionQ?br />
我们常常看到工厂模式中类装入?class loader)中也用Singleton模式实现?因ؓ被装入的cd际也属于资源?br />
如何使用?
一般Singleton模式通常有几UŞ?
public class Singleton { private Singleton(){} //在自己内部定义自׃个实例,是不是很奇怪? private static Singleton instance = new Singleton(); //q里提供了一个供外部讉K本class的静态方法,可以直接讉K
|
W二UŞ?
public class Singleton {
private static Singleton instance = null; }
|
使用Singleton.getInstance()可以讉K单态类?/p>
上面W二中Ş式是lazy initializationQ也是说第一ơ调用时初始SingletonQ以后就不用再生成了?/p>
注意到lazy initialization形式中的synchronizedQ这个synchronized很重要,如果没有synchronizedQ那么用getInstance()是有可能得到多个Singleton实例。关于lazy initialization的Singleton有很多涉及double-checked locking (DCL)的讨论,有兴者进一步研I?/p>
一般认为第一UŞ式要更加安全些?br />
使用Singleton注意事项Q?br /> 有时在某些情况下Q用Singletonq不能达到Singleton的目的,如有多个Singleton对象同时被不同的c装入器装蝲Q在EJBq样的分布式pȝ中用也要注意这U情况,因ؓEJB是跨服务器,跨JVM的?/p>
我们以SUN公司的宠物店源码(Pet Store 1.3.1)的ServiceLocatorZE微分析一下:
在Pet Store中ServiceLocator有两U,一个是EJB目录下;一个是WEB目录下,我们查这两个ServiceLocator会发现内容差不多Q都是提供EJB的查询定位服务,可是Z么要分开呢?仔细研究对这两种ServiceLocator才发现区别:在WEB中的ServiceLocator的采取Singleton模式QServiceLocator属于资源定位Q理所当然应该使用Singleton模式。但是在EJB中,Singleton模式已经失去作用Q所以ServiceLocator才分成两U,一U面向WEB服务的,一U是面向EJB服务的?/p>
Singleton模式看v来简单,使用Ҏ也很方便Q但是真正用好,是非怸ҎQ需要对Java的类 U程 内存{概忉|相当的了解?/p>
MQ如果你的应用基于容器,那么Singleton模式用或者不用,可以使用相关替代技术?/p>
q一步深入可参考:
Double-checked locking and the Singleton pattern
When is a singleton not a singleton?