??xml version="1.0" encoding="utf-8" standalone="yes"?> 版权信息: 可以L转蝲, 转蝲时请务必以超链接形式标明文章原文出处, 即下面的声明. 原文出处Q?a style="text-decoration: none; color: #0044aa;">http://blog.chenlb.com/2009/06/java-classloader-architecture.html jvm classLoader architectureQ?/strong> cd载器的特性:(x) classloader-architecture classloader-class-diagram cd中, BootstrapClassLoader是一个单独的javac, 其实在这里, 不应该叫他是一个javacR因为,它已l完全不用java实现?jin)。它是在jvm启动Ӟ p构造v来的Q?负责javaq_核心(j)库?/p> 自定义类加蝲器加载一个类的步?/strong> classloader-load-class ClassLoader cd载逻辑分析Q?以下逻辑是除 BootstrapClassLoader 外的cd载器加蝲程Q?/strong> U程上下文类加蝲?/strong> 以上代码摘自sun.misc.Launch的无参构造函数Launch()?/p> 使用U程上下文类加蝲? 可以在执行线E中, 抛弃双亲委派加蝲链模? 使用U程上下文里的类加蝲器加载类. U程上下文从Ҏ(gu)解决?jin)一般应用不能违背双亲委z模式的问题. 随着多核时代的来? 怿多线E开发将?x)越来越多地q入E序员的实际~码q程? 因此, 当然, 好东襉K有利? 使用U程上下文加载类, 也要注意, 保证多根需要通信的线E间的类加蝲器应该是同一? Z么要使用q种双亲委托模式呢? java动态蝲入class的两U方式:(x) 用Class.forName加蝲c?/strong> Class.forName使用的是被调用者的cd载器来加载类的?br />q种Ҏ(gu)? 证明?jin)javacd载器中的名称I间是唯一? 不会(x)怺q扰?br />卛_一般情况下, 保证同一个类中所兌的其他类都是由当前类的类加蝲器所加蝲的?/p> 上面?ClassLoader.getCallerClassLoader 是得到调用当前forNameҎ(gu)的类的类加蝲?/p> static块在什么时候执? 各个javacȝ哪些classLoader加蝲? NoClassDefFoundError和ClassNotFoundException
主要负责jdk_home/lib目录下的核心(j) api ?-Xbootclasspath 选项指定的jar包装入工作?/li>
主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作?/li>
主要负责java -classpath/-Djava.class.path所指的目录下的cMjar包装入工作?/li>
在程序运行期? 通过java.lang.ClassLoader的子cd态加载class文g, 体现java动态实时类装入Ҏ(gu)?/li>
java默认的线E上下文cd载器?pȝcd载器(AppClassLoader)?/p>
典型的例子有, 通过U程上下文来加蝲W三方库jndi实现, 而不依赖于双亲委z?
大部分java app服务?jboss, tomcat..)也是采用contextClassLoader来处理web服务?br />q有一些采?hotswap Ҏ(gu)的框架, 也用了(jin)U程上下文类加蝲? 比如 seasar (full stack framework in japenese).
使javacd载体pL得更灉|.
在编写基设施Ӟ 通过使用U程上下文来加蝲c? 应该是一个很好的选择?/p>
防止因ؓ(f)不同的类加蝲? Dcd转换异常(ClassCastException)?/p>
]]>
1Q用的地方Q树(wi)形结构,分支l构{?/p>
2Q用的好处Q降低客L(fng)的用,Z(jin)辑ֈ元g与组合g使用的一致性,增加?jin)元件的~码
3Q用后的坏处:(x)代码不容易理解,需要你认真ȝIӞ发现元g与组合g是怎么l合?br />
二:(x)一个实际的例子
d形,q个模式Q稍微要隄解一点,有了(jin)例子p明了(jin)一切,我画的图是用接口做的Q代码实现是抽象cMؓ(f)基类Q你自己选择?jin),接口也可以?/p>
1Q先建立囑Ş元g
package com.mike.pattern.structure.composite;
/**
* 囑Ş元g
*
* @author taoyu
*
* @since 2010-6-23
*/
public abstract class Graph {
/**囑Ş名称*/
protected String name;
public Graph(String name){
this.name=name;
}
/**d*/
public abstract void draw()throws GraphException;
/**d囑Ş*/
public abstract void add(Graph graph)throws GraphException;
/**UL囑Ş*/
public abstract void remove(Graph graph)throws GraphException;
}
2)建立基础囑Ş?/strong>
package com.mike.pattern.structure.composite;
import static com.mike.util.Print.print;
/**
* 圆图?br />*
* @author taoyu
*
* @since 2010-6-23
*/
public class Circle extends Graph {
public Circle(String name){
super(name);
}
/**
* 圆添加图?br />* @throws GraphException
*/
@Override
public void add(Graph graph) throws GraphException {
throw new GraphException("圆是基础囑ŞQ不能添?);
}
/**
* 圆画?br />*/
@Override
public void draw()throws GraphException {
print(name+"d?);
}
/**
* 圆移掉图?br />*/
@Override
public void remove(Graph graph)throws GraphException {
throw new GraphException("圆是基础囑ŞQ不能移?);
}
}
3Q徏立基囑Ş长方?/strong>
package com.mike.pattern.structure.composite;
import static com.mike.util.Print.print;
/**
* 长方?br />*
* @author taoyu
*
* @since 2010-6-23
*/
public class Rectangle extends Graph {
public Rectangle(String name){
super(name);
}
/**
* 长方形添?br />*/
@Override
public void add(Graph graph) throws GraphException {
throw new GraphException("长方形是基础囑ŞQ不能添?);
}
/**
* 画长方Ş
*/
@Override
public void draw() throws GraphException {
print(name+"d?);
}
@Override
public void remove(Graph graph) throws GraphException {
throw new GraphException("长方形是基础囑ŞQ不能移?);
}
}
4Q最后简历组合图?/strong>
package com.mike.pattern.structure.composite;
import java.util.ArrayList;
import java.util.List;
import static com.mike.util.Print.print;
/**
* 囑Şl合?br />*
* @author taoyu
*
* @since 2010-6-23
*/
public class Picture extends Graph {
private List<Graph> graphs;
public Picture(String name){
super(name);
/**默认?0个长?/
graphs=new ArrayList<Graph>();
}
/**
* d囑Ş元g
*/
@Override
public void add(Graph graph) throws GraphException {
graphs.add(graph);
}
/**
* 囑Ş元gd
*/
@Override
public void draw() throws GraphException {
print("囑Ş容器Q?+name+" 开始创?);
for(Graph g : graphs){
g.draw();
}
}
/**
* 囑Ş元gUL囑Ş元g
*/
@Override
public void remove(Graph graph) throws GraphException {
graphs.remove(graph);
}
}
5Q最后测?/strong>
public static void main(String[] args)throws GraphException {
/**M个圆Q圆里包含一个圆和长方Ş*/
Picture picture=new Picture("立方体圆");
picture.add(new Circle("?));
picture.add(new Rectangle("长方?));
Picture root=new Picture("怪物囑Ş");
root.add(new Circle("?));
root.add(picture);
root.draw();
}
6)使用?j)得Q的降低了(jin)客户端的使用情况Q让整个囑Ş可控?jin),当是你要深入ȝ解,才真名明白采用该模式的含义,不太?gu)理解?/p>
1Q用的地方Q我想用两个不同类的方法,q个时候你需要把它们l合h使用
2Q目前用的情况Q我?x)把两个cȝL(fng)合的方式攑ֈ一P~程思想think in java里已l提CQ能量用组合就用组合,l承一般考虑再后?/p>
3Q用后的好处:(x)你不需要改动以前的代码Q只是新装?jin)一新类Q由q个cL提供两个cȝҎ(gu)Q这个时候:(x)一定会(x)惛_facade外观模式Q本来是多个cM用的情况Q我新封装成一个类来用,而这个类我采用组合的方式来包装新的方法。我的理解是Q设计模式本w就是ؓ(f)?jin)帮助解决特定的业务场景而故意把模式划分对应的模式类别,其实大多数情况,都解决了(jin)同样的问题,q个时候其实没有必要过多的U缠到模式的名字上了(jin)Q你有好的注意,你甚臛_一个新的名字来概括q样的用场景?/p>
4Q用的坏处Q适配器模式,有两U方式来实现。一个是l合一个是l承Q我觉得Q首先应该考虑l合Q能用组合就不要用承,q是W一个。第二个Q你采用l承来实玎ͼ那肯定会(x)加大l承?wi)结构,如果你的l承关系本n很复杂?jin),q肯定会(x)加大l承关系的维护,不有利于代码的理解,或则更加J琐。承是Z(jin)解决重用的ؓ(f)题而出现的Q所以我觉得不应该滥用承,有机?x)可以考虑同样别的Ҏ(gu)?br />
二:(x)一个实际的例子
兌营销的例子,用户购买完商品后Q我又推荐他相关别的商品
׃减少代码Q方法我都不采用接口Q直接由cL提供Q代码只是一个范例而已Q都_?jin)?/p>
1)创徏订单信息
public class Order {
private Long orderId;
private String nickName;
public Order(Long orderId,String nickName){
this.orderId=orderId;
this.nickName=nickName;
}
/**
* 用户下订?br />*/
public void insertOrder(){
}
}
2Q商品信?/strong>
public class Auction {
/**商品名称*/
private String name;
/**刉商*/
private String company;
/**刉日?/
private Date date;
public Auction(String name,String company, Date date){
this.name=name;
this.company=company;
this.date=date;
}
/**
* 推广的商品列?br />*/
public void commendAuction(){
}
}
3Q购?/strong>
public class Trade {
/**用户订单*/
private Order order;
/**商品信息*/
private Auction auction;
public Trade(Order order ,Auction auction){
this.order=order;
this.auction=auction;
}
/**
* 用户产生订单以及(qing)后箋(hu)的事?br />*/
public void trade(){
/**下订?/
order.insertOrder();
/**兌推荐相关的商?/
auction.commendAuction();
}
}
4Q用心(j)得:(x)其实外面采用?jin)很多承的方式Qorderl承auction之后Q利用super .inserOrder()再加一个auction.recommendAuction(),实际上大同小异,我到觉得采用l合更容易理解以?qing)代码更加优点?/p>
1)使用到的地方Q如果你惛_建类似汽车这L(fng)对象Q首先要创徏轮子Q玻璃,桌椅Q发动机Q外廓等Q这些部仉创徏好后Q最后创建汽车成品,部g的创建和汽R的组装过E本w都很复杂的情况Q希望把部g的创建和成品的组装分开来做Q这h要做的事情分割开来,降低对象实现的复杂度Q也降低以后成本的维护,把汽车的部g创徏和组装过E独立出两个对应的工厂来做,有点cM建立两个对应的部件创建工厂和汽Rl装工厂两个工厂Q而工厂只是创Z个成品,q没有把里面的步骤也独立出来Q应该说Builder模式比工厂模式又q了(jin)一步?/p>
2Q采用Builder模式后的好处Q把一个负责的对象的创E分解,把一个对象的创徏分成两个对象来负责创建,代码更有利于l护Q可扩性比较好?/p>
3Q采用Builder模式后的坏处Q实现v来,对应的接口以?qing)部件的对象的创建比较多Q代码相Ҏ(gu)Ԍ比较多了(jin)Q估计刚开始你?x)有?gu)Q这个可以考虑代码_的问题,增加代码的可L?
二:(x)一个实际的例子
汽R的组?/strong>
1)首先创徏汽Rq个成品对象Q包含什么的成员
public class Car implements Serializable{
/**
* 汽R序列?br />*/
private static final long serialVersionUID = 1L;
/**汽R轮子*/
private Wheel wheel;
/**汽R发动?/
private Engine engine;
/**汽Rȝ*/
private Glass glass;
/**汽R座椅*/
private Chair chair;
public Wheel getWheel() {
return wheel;
}
public void setWheel(Wheel wheel) {
this.wheel = wheel;
}
public Engine getEngine() {
return engine;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
public Glass getGlass() {
return glass;
}
public void setGlass(Glass glass) {
this.glass = glass;
}
public Chair getChair() {
return chair;
}
public void setChair(Chair chair) {
this.chair = chair;
}
}
2Q创建对应汽车零部g
public class Wheel {
public Wheel(){
print("--汽R轮子构徏完毕--");
}
}
public class Engine {
public Engine(){
print("--汽R发动机构建完?-");
}
}
public class Glass {
public Glass(){
print("--汽Rȝ构徏完毕--");
}
}
public class Chair {
public Chair(){
print("--汽R座椅构徏完毕--");
}
}
3Q开始重点了(jin)Q汽车成品的l装q程
public interface Builder {
/**l装汽R轮子*/
public void buildWheel();
/**l装汽R发动?/
public void buildEngine();
/**l装汽Rȝ*/
public void buildGlass();
/**l装汽R座椅*/
public void buildChair();
/**q回l装好的汽R*/
public Car getCar();
}
以及(qing)实现c?/p>
public class CarBuilder implements Builder {
/**汽R成品*/
private Car car;
public CarBuilder(){
car=new Car();
}
/**l装汽R轮子*/
@Override
public void buildChair() {
car.setChair(new Chair());
}
/**l装汽R发动?/
@Override
public void buildEngine() {
car.setEngine(new Engine());
}
/**l装汽Rȝ*/
@Override
public void buildGlass() {
car.setGlass(new Glass());
}
/**l装汽R座椅*/
@Override
public void buildWheel() {
car.setWheel(new Wheel());
}
/**q回l装好的汽R*/
@Override
public Car getCar() {
buildChair();
buildEngine();
buildGlass();
buildWheel();
print("--整个汽R构徏完毕--");
return car;
}
}
4Q最后汽车创建测?/strong>
public static void main(String[] args) {
/**创徏汽Rl装*/
Builder carBuilder=new CarBuilder();
Car car=carBuilder.getCar();
}
最后输出:(x)
--汽R座椅构徏完毕--
--汽R发动机构建完?-
--汽Rȝ构徏完毕--
--汽R轮子构徏完毕--
--整个汽R构徏完毕--
5Q?strong>体会(x)?j)得Q?/strong>Builder模式实际的重点就把汽车的l装q程和零部g的生产分开来实玎ͼ雉件的生成主要靠自q对象来实玎ͼ我上面只是在构造函数里创徏?jin),比较单,而重Ҏ(gu)车的l装则交lC(j)arBuilder来实玎ͼ最l由builder来先负责雉件的创徏Q最后返回出成品的汽车?/p>
1Q经怋用的地方Q一个类只有一个实例,eg:面讉Kl计pvQ统计的个数只能保证一个实例的l计?/p>
2Q我们目前用的情况Q比如我惛_Z个对象,q个对象希望只有一份实例的l护Q在内存的保存(sh)只有一份,也就是在同一个jvm的java堆里只保存(sh)份实例对象,所以你?x)想一办法Q在创徏q个对象的时候,已l能保证只有一份?/p>
3Q怎么改进Q定义该对象的时候,׃证是同一份实例,比如Q定义ؓ(f)U有构造函敎ͼ防止通过new的方式可以创建对象,然后在对象里定义一个静(rn)态的U有成员Q本w对象的一个实例)(j)Q然后再创徏一个外面访问该对象的方法就好了(jin)?/p>
4Q改q的好处Q代码在~译代码q个U别p控制?jin),不至于在jvm里运行的时候才来保证,把唯一实例的创Z证在~译阶段Qjvm里内存只有一份,从而内存占有率更低Q以?qing)更方便java垃圾回收
5Q改q后的坏处:(x)只能是代码稍微需要更多点Q其实大家最后发现改q后的坏处,都是代码定义比之间要多一点,但以后的l护代码降下来?jin),也短暂的代码量偏大来换取以后代码的精?br />
二:(x)一个实际的例子
M的例?/p>
package com.mike.pattern.singleton;
/**
* ȝ
*
* @author taoyu
*
* @since 2010-6-22
*/
public class President {
private President(){
System.out.println("ȝ已经选D出来?);
}
/**ȝ只有一?/
private static President president=new President();
/**
* q回ȝ
*/
public static President getPresident(){
return president;
}
/**
* ȝ宣布选D成功
*/
public void announce(){
System.out.println("伟大的中国h民,我将成你们新的ȝ");
}
}
/**
* @param args
*/
public static void main(String[] args) {
President president=President.getPresident();
president.announce();
}
1Q子c过多,不容易管理;构造对象过E过长;_代码创徏Q?br />
2)目前我们代码情况Q?~写代码的时候,我们l常都在new对象Q创Z个个的对象,而且q有很多ȝ(ch)的创建方式,eg:HashMap<String,Float> grade=new HashMap<String,Float>(),q样的代码创建方式太冗长?jin),N你没有想q把q个创徏变的短一点么Q比如:(x)HashMap<String,Float>grade=HashMapFactory.new(),可以把你创徏_一点;你也可以q有别的需求,在创建对象的时候,你需要不同的情况Q创建统一U类别的对象Qeg:我想生成不同的汽车,创徏车,创徏卡RQ创建公交汽车等{,都属于同U类别:(x)汽RQ你N没有惌Q我把这些创建的对象在一个工厂里来负责创建,我把创徏分开化,交给一人来负责Q这样可以让代码更加Ҏ(gu)理Q创建方式也可以单点?/p>
比如QCar BMW=CarFactory.create(bmw); 把创建new׃个统一负责Q这L(fng)理v来相当方?/p>
3Q怎么改进Q这个时候,你会(x)惛_Q创样同cd的东西,我把q个权利分出去,让一个h来单独管理,它只负责创徏我的对象q个事情Q所以你单独历一个对象来创徏同类的对象,q个时候,你想q个东西有点像工厂一P生成同样的品,所以取?jin)个名字Q工厂模式,思义Q只负责对象的创?/p>
4Q改q后的好处:(x)代码更加Ҏ(gu)理?jin),代码的创z很多?/p>
5Q改q后的坏处:(x)那就是你需要单独加一个工厂对象来负责创徏Q多需要写点代码?br />
2.一个实际的例子
创徏宝马汽R与奔驰汽车的例子
1Q先提取Z个汽车的公用接口Car
public interface Car{
/**行驶*/
public void drive();
}
2)宝马和奔驰汽车对?/p>
public class BMWCar implements Car {
/**
* 汽R发动
*/
public void drive(){
System.out.println("BMW Car drive");
}
}
public class BengCar implements Car {
/**
* 汽R发动
*/
public void drive(){
System.out.println("BengChi Care drive");
}
}
3)单独一个汽车工厂来负责创徏
public class FactoryCar {
/**
* 刉汽?br />*
* @param company 汽R公司
* @return 汽R
* @throws CreateCarException 刉汽车失败异?br />*/
public static Car createCar(Company company)throws CreateCarException{
if(company==Company.BMW){
return new BMWCar();
}else if(company==Company.Beng){
return new BengCar();
}
return null;
}
}
4Q最后的代码实现Q?/p>
Car BMWCar=FactoryCar.createCar(Company.BMW);
BMWCar.drive();
2. q个时候,你发C(jin)Q本w面向对象的语言里,已经暗藏?jin)很多好处,你肯定?x)仔细d析面向对象这个语aQ认真去挖掘里面更多的奥U,最后,你发C(jin)Q原来你可以把面向对象的Ҏ(gu)提取成一个公用的实现案例Q这些案例里能帮助你解决你^时编写代码的困扰Q而这样一hQ就是所谓gof的成员,他们从^时设计徏{方面找C(jin)灉|Q徏{的设计也可以公用化以及(qing)重用化,所以他们也提取?jin)相关的软g设计斚w的公用案例,也就有了(jin)下面的相关的所?3U设计模式,而里面这么多模式Q你也可以把他们归类hQ最后发现就几类模式Q创建,l构Q行为等模式cdQ而这些现成的Ҏ(gu)Q也可以在实际应用中充分发挥作用Q随着大家的用以?qing)理解,发现其实q些所谓的模式里,你的可以让你的代码变的更加优美与简l?/p>
3. 我比较喜Ƣ把代码变的更加优美与简l,优美的代码就是一看就懂,l构很清晎ͼ而简历就是一目了(jin)?dng)又可以解决你的问题,是代码又少效率又高Q所以^时要L写java doc的习(fn)惯,q样的代码才为清晎ͼ所以才?x)更加优?/p>
4. q些是我对设计模式的理解,所以这么好的宝贝,我们不去深入的了(jin)解,的确可惜?jin),q就叫站到巨人的肩膀?....