想成为Android高手必须学习的干货

Android开发详解 专栏收录该内容
129 篇文章 1 订阅


[原]设计模式之一---工厂方法模式【Factory Method模式】

          在设计模式中,Factory Method模式是一种比较简单的设计模式,应用比较广泛,但也是一种比较重要的设计模式之一。在很多地方我们都会看到xxxFactory这样命名的类,那么,什么是Factory Method,为什么要用这个模式,如何用Java语言来实现该模式?

【1】基本概念

          FactoryMethod是一种创建性模式,它定义了一个创建对象的接口,但是却让子类来决定具体实例化哪一个类.当一个类无法预料要创建哪种类的对象或是一个类需要由子类来指定创建的对象时我们就需要用到Factory Method 模式了.简单说来,Factory Method可以根据不同的条件产生不同的实例,当然这些不同的实例通常是属于相同的类型,具有共同的父类.Factory Method把创建这些实例的具体过程封装起来了,简化了客户端的应用,也改善了程序的扩展性,使得将来可以做最小的改动就可以加入新的待创建的类. 通常我们将Factory Method作为一种标准的创建对象的方法,当发现需要更多的灵活性的时候,就开始考虑向其它创建型模式转化。

【2】简单分析

          我们先来看一下该设计模式的UML图:


上图是Factory Method 模式的结构图,让我们可以进行更方便的描述:

  1. Product: 需要创建的产品的抽象类.
  2. ConcreteProduct: Product的子类,一系列具体的产品.
  3. Creator: 抽象创建器接口,声明返回Product类型对象的Factory Method.
  4. ConcreteCreator: 具体的创建器,重写Creator中的Factory Method,返回ConcreteProduct类型的实例.

同时可以清楚的看出这样的平行对应关系: Product <====> Creator ; ConreteProduct <====> ConreteCreator

抽象产品对应抽象创建器,具体产品对应具体创建器.这样做的好处是什么呢?为什么我们不直接用具体的产品和具体的创建器完成需求呢?实际上我们也可以这样做.但通过Factory Method模式来完成,客户(client)只需引用抽象的Product和Creater,对具体的ConcreteProduct和ConcreteCreator可以毫不关心,这样做我们可以获得额外的好处:

  • 首先客户端可以统一从抽象创建器获取产生的实例,Creator的作用将client和产品创建过程分离开来,客户不用操心返回的是那一个具体的产品,也不用关心这些产品是如何创建的.同时,ConcreteProduct也被隐藏在Product后面,ConreteProduct继承了Product的所有属性,并实现了Product中定义的抽象方法,按照Java中的对象造型(cast)原则,通过ConcreteCreator产生的ConcreteProduct可以自动的上溯造型成Product.这样一来,实质内容不同的ConcreteProduct就可以在形式上统一为Product,通过Creator提供给client来访问.
  • 其次,当我们添加一个新的ConcreteCreator时,由于Creator所提供的接口不变,客户端程序不会有丝毫的改动,不会带来动一发而牵全身的灾难, 这就是良好封装性的体现.但如果直接用ConcreteProduct和ConcreteCreator两个类是无论如何也做不到这点的. 优良的面向对象设计鼓励使用封装(encapsulation)和委托(delegation),而Factory Method模式就是使用了封装和委托的典型例子,这里封装是通过抽象创建器Creator来体现的,而委托则是通过抽象创建器把创建对象的责任完全交给具体创建器ConcreteCreator来体现的.
【3】如何用java语言来实现该模式

该模式采用一个Shape(形状)的经典例子作为一个实例来展示如何实现Factory Method模式,先看下代码的结构图:


3.1 首先定义一个抽象类Shape,定义两个抽象的方法.

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.product;  
  2.   
  3. /**  
  4.  * Product: 需要创建的产品的抽象类.  
  5.  * @author Andy.Chen  
  6.  *  
  7.  */  
  8. public abstract class Shape {  
  9.       
  10.     public String name;  
  11.     public Shape(String aName){  
  12.         this.name = aName;  
  13.     }  
  14.       
  15.     //绘画  
  16.     public abstract void draw();  
  17.     //擦除  
  18.     public abstract void erase();  
  19.   
  20. }</span>  
3.2  定义 Shape的两个子类: Circle, Square,实现Shape中定义的抽象方法

Circle中的源码如下:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concreteproduct;  
  2.   
  3. import com.andyidea.patterns.product.Shape;  
  4.   
  5. /**  
  6.  * 圆形子类(ConcreteProduct: Product的子类,一系列具体的产品.)  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class Circle extends Shape{  
  11.   
  12.     public Circle(String name) {  
  13.         super(name);  
  14.     }  
  15.   
  16.     @Override  
  17.     public void draw() {  
  18.         System.out.println("It will draw a Circle");  
  19.     }  
  20.   
  21.     @Override  
  22.     public void erase() {  
  23.         System.out.println("It will erase a Circle");  
  24.     }  
  25.   
  26. }</span>  
Square中的源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concreteproduct;  
  2.   
  3. import com.andyidea.patterns.product.Shape;  
  4.   
  5. /**  
  6.  * 方形子类(ConcreteProduct: Product的子类,一系列具体的产品.)  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class Square extends Shape{  
  11.   
  12.     public Square(String name) {  
  13.         super(name);  
  14.     }  
  15.   
  16.     @Override  
  17.     public void draw() {  
  18.         System.out.println("It will draw a Square");  
  19.     }  
  20.   
  21.     @Override  
  22.     public void erase() {  
  23.         System.out.println("It will erase a Square");  
  24.     }  
  25.   
  26. }</span>  
3.3  定义抽象的创建器,anOperation调用factoryMethod创建一个对象,并对该对象进行一系列操作.

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.creator;  
  2.   
  3. import com.andyidea.patterns.product.Shape;  
  4.   
  5. /**  
  6.  * Creator: 抽象创建器接口,声明返回Product类型对象的Factory Method.  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public abstract class ShapeFactory {  
  11.       
  12.     protected abstract Shape factoryMethod(String aName);  
  13.       
  14.     public void anOperation(String aName){  
  15.         Shape s = factoryMethod(aName);  
  16.         System.out.println("The current shape is: " + s.name);  
  17.         s.draw();  
  18.         s.erase();  
  19.     }  
  20.   
  21. }</span>  
3.4  定义与circle和square相对应的两个具体创建器CircleFactory,SquareFactory,实现父类的methodFactory方法

CircleFactory中的源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concretecreator;  
  2.   
  3. import com.andyidea.patterns.concreteproduct.Circle;  
  4. import com.andyidea.patterns.creator.ShapeFactory;  
  5. import com.andyidea.patterns.product.Shape;  
  6.   
  7. /**  
  8.  * ConcreteCreator: 具体的创建器,重写Creator中的Factory Method,  
  9.  * 返回ConcreteProduct类型的实例.  
  10.  * @author Andy.Chen  
  11.  *  
  12.  */  
  13. public class CircleFactory extends ShapeFactory {  
  14.   
  15.     @Override  
  16.     protected Shape factoryMethod(String aName) {  
  17.         return new Circle(aName + " (created by CircleFactory)");  
  18.     }  
  19.   
  20. }</span>  
SquareFactory中的源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concretecreator;  
  2.   
  3. import com.andyidea.patterns.concreteproduct.Square;  
  4. import com.andyidea.patterns.creator.ShapeFactory;  
  5. import com.andyidea.patterns.product.Shape;  
  6.   
  7. /**  
  8.  * ConcreteCreator: 具体的创建器,重写Creator中的Factory Method,  
  9.  * 返回ConcreteProduct类型的实例.  
  10.  * @author Andy.Chen  
  11.  *  
  12.  */  
  13. public class SquareFactory extends ShapeFactory {  
  14.   
  15.     @Override  
  16.     protected Shape factoryMethod(String aName) {  
  17.         return new Square(aName + " (created by SquareFactory)");  
  18.     }  
  19.   
  20. }</span>  
3.5  测试类MainClient:这个客户端程序没有罗嗦的条件判断语句,也无需关心ConcreteProduct和ConcreteCreator的细节(因为这里我用anOperation封装了Product里的两个方法,所以连Product的影子也没看见,当然把Product里方法的具体调用放到客户程序中也是不错的).
[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.client;  
  2.   
  3. import com.andyidea.patterns.concretecreator.CircleFactory;  
  4. import com.andyidea.patterns.concretecreator.SquareFactory;  
  5. import com.andyidea.patterns.creator.ShapeFactory;  
  6.   
  7. /**  
  8.  * 测试设计模式类  
  9.  * @author Andy.Chen  
  10.  *  
  11.  */  
  12. public class MainClient {  
  13.   
  14.     public static void main(String[] args) {  
  15.         ShapeFactory sf1 = new CircleFactory();  
  16.         ShapeFactory sf2 = new SquareFactory();  
  17.           
  18.         System.out.println("Welcome to Andy.Chen Blog!" +"\n"   
  19.                            +"Factory Method Patterns." +"\n"  
  20.                            +"-------------------------------");  
  21.           
  22.         sf1.anOperation("Shape-Circle");  
  23.         sf2.anOperation("Shape-Square");  
  24.     }  
  25. }</span>  
【4】程序运行结果如下:

[html]  view plain copy print ?
  1. <span style="color:#009900;">Welcome to Andy.Chen Blog!  
  2. Factory Method Patterns.  
  3. -------------------------------  
  4. The current shape is: Shape-Circle (created by CircleFactory)  
  5. It will draw a Circle  
  6. It will erase a Circle  
  7. The current shape is: Shape-Square (created by SquareFactory)  
  8. It will draw a Square  
  9. It will erase a Square</span>  
【5】总结:用Factory Method模式创建对象并不一定会让我们的代码更短,实事上往往更长,我们也使用了更多的类,真正的目的在于这样可以灵活的,有弹性的创建不确定的对象.而且,代码的可重用性提高了,客户端的应用简化了,客户程序的代码会大大减少,变的更具可读性。







作者:cjjky 发表于2012-3-3 0:29:42 原文链接
阅读:4897 评论:14 查看评论

[原]设计模式之二 --- Singleton 模式

【1】基本概念

       Singleton 是一种创建性模式,它用来确保只产生一个实例,并提供一个访问它的全局访问点。对一些类来说,保证只有一个实例是很重要的,比如有的时候,数据库连接或 Socket 连接要受到一定的限制,必须保持同一时间只能有一个连接的存在。

【2】简单分析

        我们先来看一下该设计模式的UML结构图:


为了实现 Singleton 模式,我们需要的是一个静态的变量,能够在不创建对象的情况下记忆是否已经产生过实例了。静态变量或静态方法都可以在不产生具体实例的情况下直接调用,这样的变量或方法不会因为类的实例化而有所改变。在上面的模式结构图中的 uniqueInstance 就是这个独立的静态变量,它可以记忆对象是否已经实例化了,在静态方法 getInstance() 中对这个变量进行判断,若没有实例化过就产生一个新的对象,如果已经实例化了则不再产生新的对象,仍然返回以前产生的实例。

【3】如何用java语言来实现该设计模式:以下采用2种方法来实现该模式。

第一种方法:用静态方法实现 Singleton 这种方法是使用静态方法来监视实例的创建。为了防止创建一个以上的实例,我们把构造器声明为 private。这样可以防止客户端程序员通过除由我们提供的方法之外的任意方式来创建一个实例。如果不把构造器声明为private,编译器则会创建一个默认的public的构造器。

具体实现的代码如下:

[html]  view plain copy print ?
  1. <span style="font-size: 16px;"><span style="color:#009900;">package com.andyidea.patterns.singleton;  
  2.   
  3. public class Singleton {  
  4.       
  5.     private static Singleton s;  
  6.       
  7.     /**  
  8.      * 把构造函数设置为private  
  9.      */  
  10.     private Singleton(){  
  11.           
  12.     }  
  13.       
  14.     /**  
  15.      * 实例化对象的唯一接口  
  16.      * @return  
  17.      */  
  18.     public static Singleton getInstance(){  
  19.         if(s == null){  
  20.             s = new Singleton();  
  21.         }  
  22.         return s;  
  23.     }  
  24.   
  25. }</span></span>  
测试类代码如下:

[html]  view plain copy print ?
  1. <span style="font-size: 16px;"><span style="color:#009900;">package com.andyidea.patterns.client;  
  2.   
  3. import com.andyidea.patterns.singleton.Singleton;  
  4.   
  5. /**  
  6.  * 设计模式测试类  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class MainClient {  
  11.   
  12.     public static void main(String[] args) {  
  13.         Singleton s1 = Singleton.getInstance();  
  14.         Singleton s2 = Singleton.getInstance();  
  15.           
  16.         System.out.println("Welcome to Andy.Chen Blog!" +"\n"   
  17.                    +"Singleton Patterns." +"\n"  
  18.                    +"-------------------------------");  
  19.           
  20.         if (s1==s2)  
  21.           System.out.println("s1 is the same instance with s2");  
  22.         else  
  23.           System.out.println("s1 is not the same instance with s2");  
  24.     }  
  25. }</span></span>  
程序运行的结果如下:

[html]  view plain copy print ?
  1. <span style="color:#009900;">Welcome to Andy.Chen Blog!  
  2. Singleton Patterns.  
  3. -------------------------------  
  4. s1 is the same instance with s2</span>  
第二种方法:以静态变量为标志实现 Singleton 在类中嵌入一个静态变量做为标志,每次都在进入构造器的时候进行检查。问题在于构造器没有返回类型,如果确定创建一个实例成功与否.一个方法是调用一个函数来检查创建是否成功,然后简单的返回一个来自静态变量的值,但是这样做是不优雅的,而且容易发生错误。比较好的做法是创建一个当创建了一个以上的实例时可以抛出异常的类,这个类仅仅是调用父类方法,好处是用了自己创建的异常类型,错误信息更加清晰。

具体实现的代码如下:

[html]  view plain copy print ?
  1. <span style="font-size: 16px;"><span style="color:#009900;">package com.andyidea.patterns.singleton;  
  2.   
  3. public class Singleton {  
  4.       
  5.       static boolean instance_flag = false;  
  6.       public Singleton() {  
  7.         if (instance_flag)  
  8.           throw new SingletonException("Only one instance allowed");  
  9.         else  
  10.           instance_flag = true;  
  11.       }  
  12.   
  13. }</span></span>  
异常类代码如下:

[html]  view plain copy print ?
  1. <span style="font-size: 16px;"><span style="color:#009900;">package com.andyidea.patterns.singleton;  
  2.   
  3. /**  
  4.  * 异常类  
  5.  * @author Andy.Chen  
  6.  *  
  7.  */  
  8. public class SingletonException extends RuntimeException{  
  9.   
  10.     public SingletonException(String exception){  
  11.         super(exception);  
  12.     }  
  13. }</span></span>  
测试类代码如下:

[html]  view plain copy print ?
  1. <span style="font-size: 16px;"><span style="color:#009900;">package com.andyidea.patterns.client;  
  2.   
  3. import com.andyidea.patterns.singleton.Singleton;  
  4. import com.andyidea.patterns.singleton.SingletonException;  
  5.   
  6. /**  
  7.  * 设计模式测试类  
  8.  * @author Andy.Chen  
  9.  *  
  10.  */  
  11. public class MainClient {  
  12.   
  13.     public static void main(String[] args) {  
  14.           
  15.         System.out.println("Welcome to Andy.Chen Blog!" +"\n"   
  16.         +"Singleton Patterns." +"\n"  
  17.         +"-------------------------------");  
  18.           
  19.         Singleton s1, s2;  
  20.         // create one incetance--this should always work  
  21.         System.out.println("Creating one instance");  
  22.         try {  
  23.           s1 = new Singleton();  
  24.         } catch (SingletonException e) {  
  25.           System.out.println(e.getMessage());  
  26.         }  
  27.         // try to create another incetanced  
  28.         System.out.println("Creating two instance");  
  29.         try {  
  30.           s2 = new Singleton();  
  31.         } catch (SingletonException e) {  
  32.           System.out.println(e.getMessage());  
  33.         }  
  34.     }  
  35. }</span></span>  
运行结果如下:

[html]  view plain copy print ?
  1. <span style="color:#009900;">Welcome to Andy.Chen Blog!  
  2. Singleton Patterns.  
  3. -------------------------------  
  4. Creating one instance  
  5. Creating two instance  
  6. Only one instance allowed</span>  
从输出的结果可以看出,第一个实例可以顺利创建,创建第二个实例的时候抛出了我们自定义的异常信息。


作者:cjjky 发表于2012-3-4 19:41:09 原文链接
阅读:1338 评论:6 查看评论

[原]设计模式之三 --- 策略模式(Strategy Pattern)

           策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。

【1】基本概念

          策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。

【2】简单分析

          我们先来看一下该设计模式的UML结构图


上图是Strategy 模式的结构图,让我们可以进行更方便的描述:

  1. Strategy: 定义所有支持的算法的公共接口抽象类.
  2. ConcreteStrategy: 封装了具体的算法或行为,继承于Strategy
  3. Context: 用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。
      策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。
【3】如何用java语言来实现该模式
下面以一个简单的例子来展示该模式,先看下代码结构图:

3.1 首先定义一个Strategy抽象类,定义所有算法的公共接口
[html]  view plain copy print ?
  1. <span style="font-family: SimSun;"><span style="color:#009900;">package com.andyidea.patterns.strategy;  
  2.   
  3. /**  
  4.  * 抽象算法类  
  5.  * @author Andy.Chen  
  6.  *  
  7.  */  
  8. public abstract class Strategy {  
  9.       
  10.     //算法方法  
  11.     public abstract void AlgorithmInterface();  
  12.   
  13. }</span></span>  
3.2 定义具体ConcreteStrategy,分别继承Strategy
ConcreteStrategyA代码:
[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concretestrategy;  
  2.   
  3. import com.andyidea.patterns.strategy.Strategy;  
  4.   
  5. /**  
  6.  * 具体算法A  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class ConcreteStrategyA extends Strategy{  
  11.   
  12.     @Override  
  13.     public void AlgorithmInterface() {  
  14.         System.out.println("算法A实现!");  
  15.     }  
  16.   
  17. }</span>  
ConcreteStrategyB代码:
[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concretestrategy;  
  2.   
  3. import com.andyidea.patterns.strategy.Strategy;  
  4.   
  5. /**  
  6.  * 具体算法B  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class ConcreteStrategyB extends Strategy{  
  11.   
  12.     @Override  
  13.     public void AlgorithmInterface() {  
  14.         System.out.println("算法B实现!");  
  15.     }  
  16.   
  17. }</span>  
ConcreteStrategyC代码:
[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concretestrategy;  
  2.   
  3. import com.andyidea.patterns.strategy.Strategy;  
  4.   
  5. /**  
  6.  * 具体算法C  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class ConcreteStrategyC extends Strategy{  
  11.   
  12.     @Override  
  13.     public void AlgorithmInterface() {  
  14.         System.out.println("算法C实现!");  
  15.     }  
  16.   
  17. }</span>  
3.3定义Context类,维护队Strategy对象的引用。
[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.context;  
  2.   
  3. import com.andyidea.patterns.strategy.Strategy;  
  4.   
  5. /**  
  6.  * 上下文  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class Context {  
  11.       
  12.     private Strategy mStrategy;  
  13.     public Context(Strategy strategy){  
  14.         this.mStrategy = strategy;  
  15.     }  
  16.       
  17.     /**  
  18.      * 上下文接口  
  19.      */  
  20.     public void ContextInterface(){  
  21.         mStrategy.AlgorithmInterface();  
  22.     }  
  23.   
  24. }</span>  
3.4 客户端测试类 MainClient.java 源码
[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.client;  
  2.   
  3. import com.andyidea.patterns.concretestrategy.ConcreteStrategyA;  
  4. import com.andyidea.patterns.concretestrategy.ConcreteStrategyB;  
  5. import com.andyidea.patterns.concretestrategy.ConcreteStrategyC;  
  6. import com.andyidea.patterns.context.Context;  
  7.   
  8. /**  
  9.  * 客户端测试类  
  10.  * @author Andy.Chen  
  11.  *  
  12.  */  
  13. public class MainClient {  
  14.       
  15.     private static Context context;  
  16.       
  17.     public static void main(String[] args) {  
  18.           
  19.         System.out.println("Welcome to Andy.Chen Blog!" +"\n"   
  20.                    +"Strategy Patterns." +"\n"  
  21.                    +"----------------------------");  
  22.           
  23.         context = new Context(new ConcreteStrategyA());  
  24.         context.ContextInterface();  
  25.           
  26.         context = new Context(new ConcreteStrategyB());  
  27.         context.ContextInterface();  
  28.           
  29.         context = new Context(new ConcreteStrategyC());  
  30.         context.ContextInterface();  
  31.     }  
  32.       
  33. }</span>  
【4】程序运行结果如下:
[html]  view plain copy print ?
  1. <span style="color:#009900;">Welcome to Andy.Chen Blog!  
  2. Strategy Patterns.  
  3. ----------------------------  
  4. 算法A实现!  
  5. 算法B实现!  
  6. 算法C实现!</span>  
从上面可以看到,策略模式的优点是简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
作者:cjjky 发表于2012-3-5 22:27:07 原文链接
阅读:1139 评论:1 查看评论

[原]设计模式之四 --- 建造(Builder)模式

【1】基本概念          

 建造(Builder)模式是一种对象构建的设计模式,它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。

【2】简单分析

我们先来看一下该设计模式的UML结构图


上图是Strategy 模式的结构图,让我们可以进行更方便的描述:

  • Builder
为创建一个Product对象的各个部件指定抽象接口。
  • ConcreteBuilder
实现Builder的接口以构造和装配该产品的各个部件。
定义并明确它所创建的表示。
提供一个检索产品的接口
  • Director
构造一个使用Builder接口的对象。
  • Product
表示被构造的复杂对象。ConcreateBuilder创建该产品的内部表示并定义它的装配过程。
在以下情况使用生成器模式:
包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
  • 当创建复杂对象(这些对象内部构建间的建造顺序通常是稳定的)的算法应该独立于该对象的组成部分以及它们的装配方式时;
  • 当构造过程必须允许被构造的对象有不同的表示时。

【3】如何用java语言来实现该模式

下面以一个简单的例子来展示该模式,先看下代码结构图:


3.1 先创建一个Product类--产品类:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.product;  
  2.   
  3. /**  
  4.  * Product--产品类  
  5.  * @author Andy.Chen  
  6.  *  
  7.  */  
  8. public class Pizza {  
  9.       
  10.     private String dough;  
  11.     private String sauce;  
  12.     private String topping;  
  13.       
  14.     public void setDough(String dough) {  
  15.         this.dough = dough;  
  16.     }  
  17.     public void setSauce(String sauce) {  
  18.         this.sauce = sauce;  
  19.     }  
  20.     public void setTopping(String topping) {  
  21.         this.topping = topping;  
  22.     }  
  23.   
  24. }</span>  
3.2 创建抽象建造者类:PizzaBuilder.java

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.builder;  
  2.   
  3. import com.andyidea.patterns.product.Pizza;  
  4.   
  5. /**  
  6.  * Builder类--抽象建造者类  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public abstract class PizzaBuilder {  
  11.       
  12.     protected Pizza pizza;  
  13.      
  14.     public Pizza getPizza() {   
  15.         return pizza;   
  16.     }  
  17.       
  18.     public void createNewPizzaProduct() {   
  19.         pizza = new Pizza();   
  20.     }  
  21.    
  22.     public abstract void buildDough();  
  23.     public abstract void buildSauce();  
  24.     public abstract void buildTopping();  
  25.   
  26. }</span>  
3.3 创建具体建造者类

HawaiianPizzaBuilder.java源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concretebuilder;  
  2.   
  3. import com.andyidea.patterns.builder.PizzaBuilder;  
  4.   
  5. /**  
  6.  * ConcreteBuilder类--具体建造者类  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class HawaiianPizzaBuilder extends PizzaBuilder {  
  11.   
  12.     @Override  
  13.     public void buildDough() {  
  14.         System.out.println("Hawaiian-Dough");  
  15.         pizza.setDough("Hawaiian-Dough");  
  16.     }  
  17.   
  18.     @Override  
  19.     public void buildSauce() {  
  20.         System.out.println("Hawaiian-Sauce");  
  21.         pizza.setSauce("Hawaiian-Sauce");  
  22.     }  
  23.   
  24.     @Override  
  25.     public void buildTopping() {  
  26.         System.out.println("Hawaiian-Topping");  
  27.         pizza.setTopping("Hawaiian-Topping");  
  28.     }  
  29.   
  30. }</span>  
SpicyPizzaBuilder.java源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concretebuilder;  
  2.   
  3. import com.andyidea.patterns.builder.PizzaBuilder;  
  4.   
  5. /**  
  6.  * ConcreteBuilder类--具体建造者类  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class SpicyPizzaBuilder extends PizzaBuilder {  
  11.   
  12.     @Override  
  13.     public void buildDough() {  
  14.         System.out.println("Spicy-Dough");  
  15.         pizza.setDough("Spicy-Dough");  
  16.     }  
  17.   
  18.     @Override  
  19.     public void buildSauce() {  
  20.         System.out.println("Spicy-Sauce");  
  21.         pizza.setSauce("Spicy-Sauce");  
  22.     }  
  23.   
  24.     @Override  
  25.     public void buildTopping() {  
  26.         System.out.println("Spicy-Topping");  
  27.         pizza.setTopping("Spicy-Topping");  
  28.     }  
  29.   
  30. }</span>  
3.4 创建指挥者(Director)类:Waiter.java

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.director;  
  2.   
  3. import com.andyidea.patterns.builder.PizzaBuilder;  
  4. import com.andyidea.patterns.product.Pizza;  
  5.   
  6. /**  
  7.  * Director类--指挥者类  
  8.  * @author Andy.Chen  
  9.  *  
  10.  */  
  11. public class Waiter {  
  12.          
  13.     private PizzaBuilder pizzaBuilder;  
  14.          
  15.     public void setPizzaBuilder (PizzaBuilder pb) {   
  16.         pizzaBuilder = pb;   
  17.     }  
  18.       
  19.     public Pizza getPizza() {   
  20.         return pizzaBuilder.getPizza();   
  21.     }  
  22.        
  23.     public void constructPizza() {  
  24.        pizzaBuilder.createNewPizzaProduct();  
  25.        pizzaBuilder.buildDough();  
  26.        pizzaBuilder.buildSauce();  
  27.        pizzaBuilder.buildTopping();  
  28.     }  
  29. }</span>  
3.5 测试类:BuilderClient.java

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.client;  
  2.   
  3. import com.andyidea.patterns.builder.PizzaBuilder;  
  4. import com.andyidea.patterns.concretebuilder.HawaiianPizzaBuilder;  
  5. import com.andyidea.patterns.concretebuilder.SpicyPizzaBuilder;  
  6. import com.andyidea.patterns.director.Waiter;  
  7. import com.andyidea.patterns.product.Pizza;  
  8.   
  9. public class BuilderClient {  
  10.   
  11.     public static void main(String[] args) {  
  12.           
  13.         System.out.println("Welcome to Andy.Chen Blog!" +"\n"   
  14.                    +"Builder Patterns." +"\n");  
  15.           
  16.         Waiter waiter = new Waiter();  
  17.         PizzaBuilder hawaiian_pizzabuilder = new HawaiianPizzaBuilder();  
  18.         PizzaBuilder spicy_pizzabuilder = new SpicyPizzaBuilder();  
  19.        
  20.         System.out.println("------------HawaiianPizza------------");  
  21.         waiter.setPizzaBuilder(hawaiian_pizzabuilder);  
  22.         waiter.constructPizza();  
  23.           
  24.         System.out.println("------------SpicyPizza------------");  
  25.         waiter.setPizzaBuilder(spicy_pizzabuilder);  
  26.         waiter.constructPizza();  
  27.        
  28.         Pizza pizza = waiter.getPizza();  
  29.     }  
  30. }</span>  
【4】程序运行结果:

[html]  view plain copy print ?
  1. <span style="color:#009900;">Welcome to Andy.Chen Blog!  
  2. Builder Patterns.  
  3.   
  4. ------------HawaiianPizza------------  
  5. Hawaiian-Dough  
  6. Hawaiian-Sauce  
  7. Hawaiian-Topping  
  8. ------------SpicyPizza------------  
  9. Spicy-Dough  
  10. Spicy-Sauce  
  11. Spicy-Topping</span>  
通过上面我们可以看到:建造者模式的好处就是使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了。

作者:cjjky 发表于2012-3-7 1:01:53 原文链接
阅读:1190 评论:1 查看评论

[原]设计模式之五 --- 代理(Proxy)模式

【1】基本概念

           代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。代理者可以作任何东西的接口:网络连接、内存中的大物件、档案或其它昂贵或无法复制的资源。

【2】简单分析

我们先看一下该设计模式的UML结构图:


我们通过上面的结构图可以看到:

Subject类:定义了RealSubject和Proxy的共用接口,这样就可以在任何使用RealSubject的地方都可以用Proxy。

RealSubject类:定义Proxy所代表的真实实体。

Proxy类:保存一个引用使得代理可以访问实体,并提供一个与Subject的接口相同的接口,这样代理就可以用来替代实体。

【3】如何用java语言实现该模式

我们先看下代码的结构图,该模式的代码实现比较简单:


3.1 Subject类:Image.java

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.subject;  
  2.   
  3. /**  
  4.  * Subject类  
  5.  * @author Andy.Chen  
  6.  *  
  7.  */  
  8. public abstract class Image {  
  9.   
  10.     public abstract void displayImage();  
  11.   
  12. }</span>  
3.2 RealSubject类:RealImage.java

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.realsubject;  
  2.   
  3. import com.andyidea.patterns.subject.Image;  
  4.   
  5. /**  
  6.  * RealSubject类  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class RealImage extends Image {  
  11.     private String filename;  
  12.     public RealImage(String filename) {   
  13.         this.filename = filename;  
  14.         loadImageFromDisk();  
  15.     }  
  16.    
  17.     private void loadImageFromDisk() {  
  18.           
  19.         System.out.println("Loading   " + filename);  
  20.     }  
  21.   
  22.     @Override  
  23.     public void displayImage() {  
  24.           
  25.         System.out.println("Displaying " + filename);   
  26.     }  
  27.   
  28. }</span>  
3.3 Proxy类:ProxyImage.java

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.proxy;  
  2.   
  3. import com.andyidea.patterns.realsubject.RealImage;  
  4. import com.andyidea.patterns.subject.Image;  
  5.   
  6. /**  
  7.  * Proxy类  
  8.  * @author Andy.Chen  
  9.  *  
  10.  */  
  11. public class ProxyImage extends Image {  
  12.     private String filename;  
  13.     private Image image;  
  14.    
  15.     public ProxyImage(String filename) {   
  16.         this.filename = filename;   
  17.     }  
  18.   
  19.     @Override  
  20.     public void displayImage() {  
  21.           
  22.         if(image == null)  
  23.             image = new RealImage(filename);  
  24.           
  25.         image.displayImage();  
  26.     }  
  27.   
  28. }</span>  
3.4 客户端测试类:ProxyClient.java

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.client;  
  2.   
  3. import com.andyidea.patterns.proxy.ProxyImage;  
  4. import com.andyidea.patterns.subject.Image;  
  5.   
  6. /**  
  7.  * 代理模式客户端测试类  
  8.  * @author Andy.Chen  
  9.  *  
  10.  */  
  11. public class ProxyClient {  
  12.   
  13.     public static void main(String[] args) {  
  14.         System.out.println("Welcome to Andy.Chen Blog!" +"\n"   
  15.                    +"Proxy Patterns." +"\n"  
  16.                    +"-------------------------------");  
  17.           
  18.         Image mImage1 = new ProxyImage("Andy.Photo1");  
  19.         Image mImage2 = new ProxyImage("Andy.Photo2");  
  20.           
  21.         mImage1.displayImage();  
  22.         mImage2.displayImage();  
  23.     }  
  24. }</span>  
【4】程序运行结果:

[html]  view plain copy print ?
  1. <span style="color:#009900;">Welcome to Andy.Chen Blog!  
  2. Proxy Patterns.  
  3. -------------------------------  
  4. Loading   Andy.Photo1  
  5. Displaying Andy.Photo1  
  6. Loading   Andy.Photo2  
  7. Displaying Andy.Photo2</span>  
总结下代理模式的应用场合:

第一:远程代理,也就是为一个对象在不同的地址空间提供局部代表,这样可以隐藏一个对象存在于不同地址空间的事实。

第二:虚拟代理,是根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的真实对象。

第三:安全代理,用来控制真实对象访问时的权限。

第四:智能引用,是指当调用真实对象时,代理处理另外一些事。本文的例子就是采用了这一点。


作者:cjjky 发表于2012-3-7 22:34:56 原文链接
阅读:1370 评论:1 查看评论

[原]设计模式之六 --- 抽象工厂模式(Abstract Factory)
         每个模式都是针对一定问题的解决方案。抽象工厂模式面对的问题是多产品等级结构的系统设计。
         在学习抽象工厂具体实例之前,应该明白两个重要的概念:产品族和产品等级。

         产品族:是指位于不同产品等级结构中,功能相关联的产品组成的家族。比如AMD的CPU和ADM芯片的主板,组成一个家族。Intel的CPU和Intel芯片的主板,又组成一个家族。而这两个家族都来自于两个产品等级:CPU,主板。一个等级结构是由相同的结构的产品组成,示意图如下:


 理解这个产品结构是理解抽象工厂模式的关键所在,从上图可以看出,抽象工厂模式的每个工厂创造出来的都是一族产品,而不是一个或者一组。组是可以随意组合的!其实工厂方法模式和抽象工厂模式就这点点差别。

【1】基本概念

         抽象工厂模式是提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体类。

【2】简单分析

我们先看一下抽象工厂模式的UML结构图:

上图是 Abstract Factory 模式结构图,让我们可以进行更加方便的描述:

  1. AbstractProduct: 抽象产品,它们都有可能有两种不同的实现。
  2. ConcreteProduct:包括ProductA和ProductB, 对两个抽象产品的具体分类的实现。
  3. AbstractFactory: 抽象工厂接口,它里面应该包含所有的产品创建的抽象方法。
  4. ConcreteFactory: 包括ConcreteFactoryA和ConcreteFactoryB,具体的工厂,创建具有特定实现的产品对象。
【3】如何用java语言来实现该模式
背景:用一个分别对不同数据库(Oracle 或 SQL Server)中表( User 和 Department )的操作的实例来展示该设计模式。先看下代码的结构图:


3.1 首先定义两个抽象的产品类:IUser.java 和 IDepartment.java。

IUser.java的源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.abstractproduct;  
  2.   
  3. /**  
  4.  * 抽象产品角色:User接口  
  5.  * @author Andy.Chen  
  6.  *  
  7.  */  
  8. public interface IUser {  
  9.   
  10. }</span>  
IDepartment.java源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.abstractproduct;  
  2.   
  3. /**  
  4.  * 抽象产品角色:Department接口  
  5.  * @author Andy.Chen  
  6.  *  
  7.  */  
  8. public interface IDepartment {  
  9.   
  10. }</span>  
3.2 定义抽象工厂类:IDBFactory.java

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.abstractfactory;  
  2.   
  3. import com.andyidea.patterns.abstractproduct.IDepartment;  
  4. import com.andyidea.patterns.abstractproduct.IUser;  
  5.   
  6. /**  
  7.  * 抽象工厂角色:工厂接口  
  8.  * @author Andy.Chen  
  9.  *  
  10.  */  
  11. public interface IDBFactory {  
  12.   
  13.     public IUser createUser();  
  14.     public IDepartment createDepartment();  
  15. }</span>  
3.3创建具体产品角色类:OracleOfUser.java;OracleOfDepartment.java;SQLServerOfUser.java;SQLServerOfDepartment.java。分别继承IUser.java和IDepartment.java。

OracleOfUser.java源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concreteproduct;  
  2.   
  3. import com.andyidea.patterns.abstractproduct.IUser;  
  4.   
  5. /**  
  6.  * 具体产品角色:Oracle中的User  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class OracleOfUser implements IUser{  
  11.       
  12.     public OracleOfUser(){  
  13.         System.out.println("Oracle工厂:在Oracle中操作User表.");  
  14.     }  
  15.   
  16. }</span>  
OracleOfDepartment.java源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concreteproduct;  
  2.   
  3. import com.andyidea.patterns.abstractproduct.IDepartment;  
  4.   
  5. /**  
  6.  * 具体产品角色:Oracle中的Department  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class OracleOfDepartment implements IDepartment{  
  11.       
  12.     public OracleOfDepartment(){  
  13.         System.out.println("Oracle工厂:在Oracle中操作Department表.");  
  14.     }  
  15.   
  16. }</span>  
SQLServerOfUser.java源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concreteproduct;  
  2.   
  3. import com.andyidea.patterns.abstractproduct.IUser;  
  4.   
  5. /**  
  6.  * 具体产品角色:SQL Server中的User  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class SQLServerOfUser implements IUser{  
  11.       
  12.     public SQLServerOfUser(){  
  13.         System.out.println("SQL Server工厂:在SQL Server中操作User表.");  
  14.     }  
  15.   
  16. }</span>  
SQLServerOfDepartment.java源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concreteproduct;  
  2.   
  3. import com.andyidea.patterns.abstractproduct.IDepartment;  
  4.   
  5. /**  
  6.  * 具体产品角色:SQL Server中的Department  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class SQLServerOfDepartment implements IDepartment{  
  11.       
  12.     public SQLServerOfDepartment(){  
  13.         System.out.println("SQL Server工厂:在SQL Server中操作Department表.");  
  14.     }  
  15.   
  16. }</span>  
3.4 创建具体工厂类:OracleFactory.java和SQLServerFactory.java。

OracleFactory.java源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concretefactory;  
  2.   
  3. import com.andyidea.patterns.abstractfactory.IDBFactory;  
  4. import com.andyidea.patterns.abstractproduct.IDepartment;  
  5. import com.andyidea.patterns.abstractproduct.IUser;  
  6. import com.andyidea.patterns.concreteproduct.OracleOfDepartment;  
  7. import com.andyidea.patterns.concreteproduct.OracleOfUser;  
  8.   
  9. /**  
  10.  * 具体工厂角色:Oracle工厂  
  11.  * @author Andy.Chen  
  12.  *  
  13.  */  
  14. public class OracleFactory implements IDBFactory{  
  15.   
  16.     @Override  
  17.     public IUser createUser() {  
  18.         return new OracleOfUser();  
  19.     }  
  20.   
  21.     @Override  
  22.     public IDepartment createDepartment() {  
  23.         return new OracleOfDepartment();  
  24.     }  
  25.   
  26. }</span>  
SQLServerFactory.java源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concretefactory;  
  2.   
  3. import com.andyidea.patterns.abstractfactory.IDBFactory;  
  4. import com.andyidea.patterns.abstractproduct.IDepartment;  
  5. import com.andyidea.patterns.abstractproduct.IUser;  
  6. import com.andyidea.patterns.concreteproduct.SQLServerOfDepartment;  
  7. import com.andyidea.patterns.concreteproduct.SQLServerOfUser;  
  8.   
  9. /**  
  10.  * 具体工厂角色:SQL Server工厂  
  11.  * @author Andy.Chen  
  12.  *  
  13.  */  
  14. public class SQLServerFactory implements IDBFactory{  
  15.   
  16.     @Override  
  17.     public IUser createUser() {  
  18.         return new SQLServerOfUser();  
  19.     }  
  20.   
  21.     @Override  
  22.     public IDepartment createDepartment() {  
  23.         return new SQLServerOfDepartment();  
  24.     }  
  25.   
  26. }</span>  
3.5 客户端测试类:AbstractFactoryClient.java

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.client;  
  2.   
  3. import com.andyidea.patterns.abstractproduct.IDepartment;  
  4. import com.andyidea.patterns.abstractproduct.IUser;  
  5. import com.andyidea.patterns.concretefactory.OracleFactory;  
  6. import com.andyidea.patterns.concretefactory.SQLServerFactory;  
  7.   
  8. /**  
  9.  * 抽象工厂测试类  
  10.  * @author Andy.Chen  
  11.  *  
  12.  */  
  13. public class AbstractFactoryClient {  
  14.   
  15.     public static void main(String[] args) {  
  16.           
  17.         System.out.println("Welcome to Andy.Chen Blog!" +"\n"   
  18.                    +"Abstract Factory Patterns." +"\n"  
  19.                    +"-------------------------------");  
  20.           
  21.         IUser oracleUser,sqlUser;  
  22.         IDepartment oracleDept,sqlDept;  
  23.         OracleFactory of = new OracleFactory();  
  24.         SQLServerFactory sf = new SQLServerFactory();  
  25.           
  26.         oracleUser = of.createUser();  
  27.         oracleDept = of.createDepartment();  
  28.         sqlUser = sf.createUser();  
  29.         sqlDept = sf.createDepartment();  
  30.     }  
  31. }</span>  
【4】程序运行结果:

[html]  view plain copy print ?
  1. <span style="color:#009900;">Welcome to Andy.Chen Blog!  
  2. Abstract Factory Patterns.  
  3. -------------------------------  
  4. Oracle工厂:在Oracle中操作User表.  
  5. Oracle工厂:在Oracle中操作Department表.  
  6. SQL Server工厂:在SQL Server中操作User表.  
  7. SQL Server工厂:在SQL Server中操作Department表.</span>  
【5】总结

抽象工厂模式优点:

第一,易于交换产品系列,由于具体工厂类,例如IDBFactory factory = new OracleFactory(),在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它之需要改变具体工厂即可使用不同的产品配置。
第二,它让具体的创建实例与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。


作者:cjjky 发表于2012-3-12 23:46:58 原文链接
阅读:3959 评论:12 查看评论

[原]java同步机制:synchronized

           synchronized 是java语言关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。  

本文直接以代码的形式来展示 synchronized 关键字的使用:

【1】synchronized  Demo1:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.demo;  
  2.   
  3. /**  
  4.  * 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,  
  5.  * 一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码  
  6.  * 块以后才能执行该代码块。  
  7.  * @author Andy.Chen  
  8.  *  
  9.  */  
  10. public class Thread01 implements Runnable {  
  11.   
  12.     @Override  
  13.     public void run() {  
  14.   
  15.         synchronized (this) {  
  16.             for(int i=0;i<3;i++){  
  17.                 System.out.println(Thread.currentThread().getName()+" synchronized loop "+i);  
  18.             }  
  19.         }  
  20.     }  
  21.       
  22.     public static void main(String[] args) {  
  23.         Thread01 t01 = new Thread01();  
  24.           
  25.         System.out.println("Welcome to Andy.Chen Blog! \n"  
  26.                   +"synchronized 关键字使用 \n"  
  27.                   +"--------------------------");  
  28.           
  29.         Thread ta = new Thread(t01,"A");  
  30.         Thread tb = new Thread(t01,"B");  
  31.           
  32.         ta.start();  
  33.         tb.start();  
  34.     }  
  35.   
  36. }</span>  

运行结果如下:

[html]  view plain copy print ?
  1. <span style="color:#009900;">Welcome to Andy.Chen Blog!   
  2. synchronized 关键字使用   
  3. --------------------------  
  4. B synchronized loop 0  
  5. B synchronized loop 1  
  6. B synchronized loop 2  
  7. A synchronized loop 0  
  8. A synchronized loop 1  
  9. A synchronized loop 2</span>  

【2】synchronized  Demo2:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.demo;  
  2.   
  3. /**  
  4.  * 当一个线程访问object的一个synchronized(this)同步代码块时,  
  5.  * 另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。  
  6.  * @author Andy.Chen  
  7.  *  
  8.  */  
  9. public class Thread02 {  
  10.       
  11.     public void method01(){  
  12.         synchronized (this) {  
  13.             int i=0;  
  14.             while(i++ < 3){  
  15.                 System.out.println(Thread.currentThread().getName() +":"+ i);  
  16.                 try {  
  17.                     Thread.sleep(1000);  
  18.                 } catch (InterruptedException e) {  
  19.                     e.printStackTrace();  
  20.                 }  
  21.             }  
  22.         }  
  23.     }  
  24.       
  25.     public void method02(){  
  26.           
  27.         //第1种方式:当一个线程访问object的一个synchronized(this)同步代码块时,  
  28.         //另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。  
  29. //      int j=0;  
  30. //      while(j++ < 3){  
  31. //          System.out.println(Thread.currentThread().getName() +":"+ j);  
  32. //          try {  
  33. //              Thread.sleep(1000);  
  34. //          } catch (InterruptedException e) {  
  35. //              e.printStackTrace();  
  36. //          }  
  37. //      }  
  38.           
  39.         //第2种方式:当一个线程访问object的一个synchronized(this)同步代码块时,  
  40.         //其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。  
  41.         synchronized (this) {  
  42.             int j=0;  
  43.             while(j++ < 3){  
  44.                 System.out.println(Thread.currentThread().getName() +":"+ j);  
  45.                 try {  
  46.                     Thread.sleep(1000);  
  47.                 } catch (InterruptedException e) {  
  48.                     e.printStackTrace();  
  49.                 }  
  50.             }  
  51.         }  
  52.     }  
  53.       
  54.     /**  
  55.      * 当一个线程访问object的一个synchronized(this)同步代码块时,  
  56.      * 它就获得了这个object的对象锁。  
  57.      * 结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。  
  58.      */  
  59.     public synchronized void method3(){  
  60.         int k=0;  
  61.         while(k++ < 3){  
  62.             System.out.println(Thread.currentThread().getName() +":"+ k);  
  63.             try {  
  64.                 Thread.sleep(1000);  
  65.             } catch (InterruptedException e) {  
  66.                 e.printStackTrace();  
  67.             }  
  68.         }  
  69.     }  
  70.       
  71.     public static void main(String[] args) {  
  72.         final Thread02 t02 = new Thread02();  
  73.           
  74.         System.out.println("Welcome to Andy.Chen Blog! \n"  
  75.                   +"synchronized 关键字使用 \n"  
  76.                   +"--------------------------");  
  77.           
  78.         Thread t02A = new Thread(new Runnable() {  
  79.               
  80.             @Override  
  81.             public void run() {  
  82.                 t02.method01();  
  83.             }  
  84.         },"A");  
  85.           
  86.         Thread t02B = new Thread(new Runnable() {  
  87.               
  88.             @Override  
  89.             public void run() {  
  90.                 t02.method02();  
  91.             }  
  92.         },"B");  
  93.           
  94.         Thread t02C = new Thread(new Runnable() {  
  95.               
  96.             @Override  
  97.             public void run() {  
  98.                 t02.method3();  
  99.             }  
  100.         },"C");  
  101.           
  102.         t02A.start();  
  103.         t02B.start();  
  104.         t02C.start();  
  105.     }  
  106.   
  107. }</span>  
运行结果如下:

[html]  view plain copy print ?
  1. <span style="color:#009900;">Welcome to Andy.Chen Blog!   
  2. synchronized 关键字使用   
  3. --------------------------  
  4. B:1  
  5. B:2  
  6. B:3  
  7. C:1  
  8. C:2  
  9. C:3  
  10. A:1  
  11. A:2  
  12. A:3</span>  


【3】synchronized  Demo3:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.demo;  
  2.   
  3. /**  
  4.  * synchronized对象锁  
  5.  * @author Andy.Chen  
  6.  *  
  7.  */  
  8. public class Thread03 {  
  9.       
  10.     class InnerObject{  
  11.           
  12.         /**  
  13.          * 内部类方法1  
  14.          */  
  15.         private void innerMethod01(){  
  16.             int i=0;  
  17.             while(i++ < 3){  
  18.                 System.out.println(Thread.currentThread().getName() +":"+ i);  
  19.                 try {  
  20.                     Thread.sleep(1000);  
  21.                 } catch (InterruptedException e) {  
  22.                     e.printStackTrace();  
  23.                 }  
  24.             }  
  25.         }  
  26.           
  27.         /**  
  28.          * 内部类方法2  
  29.          */  
  30.         private void innerMethod02(){  
  31.             int j=0;  
  32.             while(j++ < 3){  
  33.                 System.out.println(Thread.currentThread().getName() +":"+ j);  
  34.                 try {  
  35.                     Thread.sleep(1000);  
  36.                 } catch (InterruptedException e) {  
  37.                     e.printStackTrace();  
  38.                 }  
  39.             }  
  40.         }  
  41.     }  
  42.       
  43.     /**  
  44.      * 外部类方法1  
  45.      * @param innerObj  
  46.      */  
  47.     private void outerMethod01(InnerObject innerObj){  
  48.         synchronized (innerObj) {  
  49.             innerObj.innerMethod01();  
  50.         }  
  51.     }  
  52.       
  53.     /**  
  54.      * 外部类方法2  
  55.      * @param innerObj  
  56.      */  
  57.     private void outerMethod02(InnerObject innerObj){  
  58.         innerObj.innerMethod02();  
  59.     }  
  60.       
  61.     public static void main(String[] args) {  
  62.         final Thread03 t03 = new Thread03();  
  63.         final InnerObject innerObj = t03.new InnerObject();  
  64.           
  65.         System.out.println("Welcome to Andy.Chen Blog! \n"  
  66.                           +"synchronized 关键字使用 \n"  
  67.                           +"--------------------------");  
  68.   
  69.         Thread t03A = new Thread(new Runnable() {  
  70.               
  71.             @Override  
  72.             public void run() {  
  73.                 t03.outerMethod01(innerObj);  
  74.             }  
  75.         },"A");  
  76.           
  77.         Thread t03B = new Thread(new Runnable() {  
  78.               
  79.             @Override  
  80.             public void run() {  
  81.                 t03.outerMethod02(innerObj);  
  82.             }  
  83.         },"B");  
  84.           
  85.         t03A.start();  
  86.         t03B.start();  
  87.     }  
  88.   
  89. }</span>  
运行结果如下:

[html]  view plain copy print ?
  1. <span style="color:#009900;">Welcome to Andy.Chen Blog!   
  2. synchronized 关键字使用   
  3. --------------------------  
  4. A:1  
  5. B:1  
  6. B:2  
  7. A:2  
  8. B:3  
  9. A:3</span>  

总结:

1.  synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。  

2. synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。  

对synchronized(this)的一些理解 
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。  

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。  

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。  

四、当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。


作者:cjjky 发表于2012-3-14 16:23:05 原文链接
阅读:1670 评论:2 查看评论

[原]设计模式之七 --- 观察者模式(Observer)

【1】基本概念

          观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。观察者模式又叫发布-订阅(Publish/Subscribe)模式。

【2】简单分析

 我们先来看一下该设计模式的UML结构图


上图是Observer 模式的结构图,让我们可以进行更方便的描述:

Subject类,它把所有对观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察着。抽象主题提供一个接口,可以增加和删除观察着对象。

Observer类,抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。

ConcreteSubject类,具体主题,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。

ConcreteObserver类,具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。

【3】如何用java语言来实现该模式

下面以一个简单的例子来展示该模式,先看下代码结构图:


该例子是这样的情景:例如:老师有电话号码,学生需要知道老师的电话号码以便于在合适的时候拨打,在这样的组合中,老师就是一个被观察者(Subject),学生就是需要知道信息的观察者,当老师的电话号码发生改变时,学生得到通知,并更新相应的电话记录。

3.1 先创建一个Subject类:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.subject;  
  2.   
  3. import com.andyidea.patterns.observer.Observer;  
  4.   
  5. /**  
  6.  * Subject(目标,Subject):    
  7.  * 目标知道它的观察者。可以有任意多个观察者观察同一个目标。  
  8.  * 提供注册和删除观察者对象的接口。  
  9.  * @author Andy.Chen  
  10.  *  
  11.  */  
  12. public interface Subject {  
  13.   
  14.     public void attach(Observer mObserver);  
  15.       
  16.     public void detach(Observer mObserver);  
  17.       
  18.     public void notice();  
  19. }</span>  
3.2 创建Observer类:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.observer;  
  2.   
  3. /**  
  4.  * Observer(观察者,Observer):  
  5.  * 为那些在目标发生改变时需要获得通知的对象定义一个更新接口。  
  6.  * @author Andy.Chen  
  7.  *  
  8.  */  
  9. public interface Observer {  
  10.   
  11.     public void update();  
  12. }</span>  
3.3 创建ConcreteSubject类:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concretesubject;  
  2.   
  3. import java.util.Vector;  
  4.   
  5. import com.andyidea.patterns.observer.Observer;  
  6. import com.andyidea.patterns.subject.Subject;  
  7.   
  8. /**  
  9.  * ConcreteSubject(具体目标,Teacher)  
  10.  * 将有关状态存入各ConcreteObserve对象。  
  11.  * 当他的状态发生改变时,向他的各个观察者发出通知。  
  12.  * @author Andy.Chen  
  13.  *  
  14.  */  
  15. public class Teacher implements Subject{  
  16.       
  17.     private String phone;  
  18.     private Vector students;  
  19.       
  20.     public Teacher(){  
  21.         phone = "";  
  22.         students = new Vector();  
  23.     }  
  24.   
  25.     @Override  
  26.     public void attach(Observer mObserver) {  
  27.         students.add(mObserver);  
  28.     }  
  29.   
  30.     @Override  
  31.     public void detach(Observer mObserver) {  
  32.         students.remove(mObserver);  
  33.     }  
  34.   
  35.     @Override  
  36.     public void notice() {  
  37.         for(int i=0;i<students.size();i++){  
  38.             ((Observer)students.get(i)).update();  
  39.         }  
  40.     }  
  41.   
  42.     public String getPhone() {  
  43.         return phone;  
  44.     }  
  45.   
  46.     public void setPhone(String phone) {  
  47.         this.phone = phone;  
  48.         notice();  
  49.     }  
  50.   
  51. }</span>  
3.4 创建ConcreteObserver类:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concreteobserver;  
  2.   
  3. import com.andyidea.patterns.concretesubject.Teacher;  
  4. import com.andyidea.patterns.observer.Observer;  
  5.   
  6. /**  
  7.  * ConcreteObserver(具体观察者, Student):  
  8.  * 维护一个指向ConcreteSubject对象的引用。  
  9.  * 存储有关状态,这些状态应与目标的状态保持一致。  
  10.  * 实现Observer的更新接口以使自身状态与目标的状态保持一致。  
  11.  * @author Andy.Chen  
  12.  *  
  13.  */  
  14. public class Student implements Observer{  
  15.   
  16.     private String name;  
  17.     private String phone;  
  18.     private Teacher mTeacher;  
  19.       
  20.     public Student(String name,Teacher t){  
  21.        this.name = name;  
  22.        mTeacher = t;  
  23.     }  
  24.       
  25.     public void show(){  
  26.        System.out.println("Name:"+name+"\nTeacher'sphone:" + phone);  
  27.     }  
  28.       
  29.     @Override  
  30.     public void update() {  
  31.         phone = mTeacher.getPhone();  
  32.     }  
  33.   
  34. }</span>  
3.5 客户端测试类:ObserverClient.java.

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.client;  
  2.   
  3. import java.util.Vector;  
  4.   
  5. import com.andyidea.patterns.concreteobserver.Student;  
  6. import com.andyidea.patterns.concretesubject.Teacher;  
  7.   
  8. /**  
  9.  * 观察者(Observer)模式测试类  
  10.  * @author Andy.Chen  
  11.  *  
  12.  */  
  13. public class ObserverClient {  
  14.   
  15.     public static void main(String[] args) {  
  16.        Vector students = new Vector();  
  17.        Teacher t = new Teacher();  
  18.        for(int i0 ;i<10;i++){  
  19.            Student st = new Student("Andy.Chen"+i,t);  
  20.            students.add(st);  
  21.            t.attach(st);  
  22.        }  
  23.          
  24.         System.out.println("Welcome to Andy.Chen Blog!" +"\n"   
  25.                    +"Observer Patterns." +"\n"  
  26.                    +"-------------------------------");  
  27.          
  28.        t.setPhone("12345678");  
  29.        for(int i=0;i<3;i++)  
  30.            ((Student)students.get(i)).show();  
  31.          
  32.        t.setPhone("87654321");  
  33.        for(int i=0;i<3;i++)  
  34.            ((Student)students.get(i)).show();  
  35.     }  
  36.       
  37. }</span>  
【4】程序运行结果如下:

[html]  view plain copy print ?
  1. <span style="color:#009900;">Welcome to Andy.Chen Blog!  
  2. Observer Patterns.  
  3. -------------------------------  
  4. Name:Andy.Chen0  
  5. Teacher'sphone:12345678  
  6. Name:Andy.Chen1  
  7. Teacher'sphone:12345678  
  8. Name:Andy.Chen2  
  9. Teacher'sphone:12345678  
  10. Name:Andy.Chen0  
  11. Teacher'sphone:87654321  
  12. Name:Andy.Chen1  
  13. Teacher'sphone:87654321  
  14. Name:Andy.Chen2  
  15. Teacher'sphone:87654321</span>  
总结:观察者模式何时适用?

1.当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中可以使他们各自独立地改变和复用。

2.当对一个对象的改变需要同时改变其它对象,而不知道具体由多少对象有待改变。

3.当一个对象必须通知其他对象,而它又不能假定其他对象是谁,换言之,你不希望这些对象是紧密耦合的。让耦合的双方都依赖于抽象,而不是依赖于具体。


作者:cjjky 发表于2012-3-22 21:32:36 原文链接
阅读:1176 评论:0 查看评论

[原]Android开发中各种问题集锦【11-20】

【11】Android导入项目时出现:Android requires compiler compliance level 5.0 or 6.0. Found '1.4' instead. Please use Android Tools > Fix Project Properties. 的解决方法?

           1. 按提示在工程文件上 右键 -> Android Tools -> Fix Project Properties ,该方法无效。

           2. 手动打开Project Properties -> java Compiler -> 选上Enable project specific settings -> 再选择 Compiler Compliance Leave(选择任意一个非默认的值) -> OK 

           3. 重复第2步,将Compiler Compliance Leave选为正确的值(该值一般是当前安装的JDK版本值,如 jdk 5 对应 1.5 ,jdk 6 对应 1.6),OK。

 

【12】 在ADT 16.0 中,定义一个ImageVIew的时候 总是提示这个[Accessibility] Missing contentDescription attribute on image警告,虽说可以不理 但总是感觉怪怪的。其实这是ADT 16.0的新特性,在一些没有文本显示的控件里,如imageView和imageButton等,ADT会提示你定义一个android:contentDescription属性,用来描述这个控件的作用。

 

【13】如何检测Android真机摄像头硬件

如果应用程序未利用manifest声明对摄像头需求进行特别指明,则应该在运行时检查一下摄像头是否可用。可用 PackageManager.hasSystemFeature() 方法来进行这种检查,代码示例如下:

[html]  view plain copy print ?
  1. <span style="font-size: 16px;"><span style="color:#009900;">/** 检查设备是否提供摄像头 */   
  2.   
  3. private boolean checkCameraHardware(Context context) {   
  4.   
  5.     if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){   
  6.   
  7.         // 摄像头存在   
  8.         return true;   
  9.   
  10.     } else {   
  11.   
  12.         // 摄像头不存在   
  13.         return false;   
  14.   
  15.     }   
  16.   
  17. }</span></span>  
Android设备可能拥有多个摄像头,比如向后的摄像头用于拍照、向前的摄像头用于摄像。Android 2.3 (API Level 9)以上版本允许利用 Camera.getNumberOfCameras() 方法来检查设备可用摄像头的数量。


【14】Java中异常类体系

         为了方便对于这些可传递对象的管理,Java API中专门设计了java.lang.Throwable类,只有该类子类的对象才可以在系统的异常传递体系中进行。该类的两个子类分别是:

         1、Error类

               该类代表错误,指程序无法恢复的异常情况。对于所有错误类型以及其子类,都不要求程序进行处理。常见的Error类例如内存溢出StackOverflowError等。

         2、Exception类

               该类代表异常,指程序有可能恢复的异常情况。该类就是整个Java语言异常类体系中的父类。使用该类,可以代表所有异常的情况。

         在Java API中,声明了几百个Exception的子类分别来代表各种各样的常见异常情况,这些类根据需要代表的情况位于不同的包中,这些类的类名均以Exception作为类名的后缀。如果遇到的异常情况,Java API中没有对应的异常类进行代表,也可以声明新的异常类来代表特定的情况。

         在这些异常类中,根据是否是程序自身导致的异常,将所有的异常类分为两种:

         1、RuntimeException及其所有子类

              该类异常属于程序运行时异常,也就是由于程序自身的问题导致产生的异常,例如数组下标越界异常ArrayIndexOutOfBoundsException等。

              该类异常在语法上不强制程序员必须处理,即使不处理这样的异常也不会出现语法错误。

         2、其它Exception子类

              该类异常属于程序外部的问题引起的异常,也就是由于程序运行时某些外部问题导致产生的异常,例如文件不存在异常FileNotFoundException等。

              该类异常在语法上强制程序员必须进行处理,如果不进行处理则会出现语法错误。

【15】  Android中引入第三方jar包时,运行程序时提示java.lang.NoClassDefFoundError异常的解决方法。

              这个问题个人觉得很怪异,引用的包中就有某个对象类,却报了这个错误,以下是个人的解决方法:

              1、在工程下新建lib文件夹,将需要的第三方包拷贝进来。
              2、将引用的第三方包,添加进工作的build path。
              3、(关键的一步)将lib设为源文件夹。如果不设置,则程序编译可以通过,但运行的时候,会报:java.lang.NoClassDefFoundError

【16】 未完待续...

作者:cjjky 发表于2012-3-23 16:30:06 原文链接
阅读:1231 评论:0 查看评论

[原]全排列算法

全排列:从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。

当m=n时所有的排列情况叫全排列。

该算法源码如下:

[html]  view plain copy print ?
  1. <span style="font-size: 16px;"><span style="color:#009900;">package com.andyidea.algorithms;  
  2.   
  3. /**  
  4.  * 全排列算法  
  5.  * @author Andy.Chen  
  6.  *  
  7.  */  
  8. public class PermutationSorter<T> {  
  9.       
  10.     /**  
  11.      * 全排列输出  
  12.      * @param array 要输出的字符数组  
  13.      * @param from 输出字符数组的起始位置  
  14.      * @param len 输出字符数组的长度  
  15.      */  
  16.     public final void permutation(T[] array, int from, int len){  
  17.         int i;  
  18.         if(from < len-1){  
  19.             permutation(array, from+1, len);  
  20.             for(i=from+1;i<len;i++){  
  21.                 swap(array,from,i);  
  22.                 permutation(array, from+1, len);  
  23.                 swap(array,from,i);  
  24.             }  
  25.         }else{  
  26.             printResult(array);  
  27.         }  
  28.     }  
  29.       
  30.     /**  
  31.      * 交换算法  
  32.      * @param array  
  33.      * @param from  
  34.      * @param to  
  35.      */  
  36.     public final void swap(T[] array,int from,int to){  
  37.         T tmp = array[from];  
  38.         array[from] = array[to];  
  39.         array[to] = tmp;  
  40.     }  
  41.       
  42.     /**  
  43.      * 打印输出全排列结果  
  44.      * @param array  
  45.      */  
  46.     public void printResult(T[] array) {  
  47.         for(int j = 0; j < array.length; j++){  
  48.             System.out.print(array[j]);  
  49.         }  
  50.         System.out.println();  
  51.     }  
  52.       
  53. }</span></span>  

作者:cjjky 发表于2012-3-27 0:14:46 原文链接
阅读:734 评论:0 查看评论

[原]Android中如何使用ViewPager实现类似laucher左右拖动效果

            现在很多Android应用在首次安装完都会有指引如何使用该应用的某些功能的指引界面,这样会获得很好的用户体验,能够帮助用户更好使用应用的某些功能。其实该功能和Android主界面的 luncher 的功能完全一样的效果,可以实现左右拖动。

下面结合 ViewPager 的实例来展示如何实现该功能,先看下该Demo的结构图:


注:ViewPager类是实现左右两个屏幕平滑地切换的一个类,是由Google 提供的, 使用ViewPager首先需要引入android-support-v4.jar这个jar包。其中工程项目中的 libs 文件夹下存放着 android-support-v4.jar这个jar包。drawable文件夹下包含有图片资源文件。

以下是工程中各个文件的源码:

main.xml源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;"><?xml version="1.0" encoding="utf-8"?>  
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <android.support.v4.view.ViewPager  
  8.         android:id="@+id/guidePages"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="wrap_content"/>  
  11.          
  12.     <RelativeLayout    
  13.         android:layout_width="fill_parent"    
  14.         android:layout_height="wrap_content"    
  15.         android:orientation="vertical" >  
  16.     <LinearLayout    
  17.         android:id="@+id/viewGroup"    
  18.         android:layout_width="fill_parent"    
  19.         android:layout_height="wrap_content"    
  20.         android:layout_alignParentBottom="true"    
  21.         android:layout_marginBottom="30dp"    
  22.         android:gravity="center_horizontal"    
  23.         android:orientation="horizontal" >    
  24.     </LinearLayout>    
  25.     </RelativeLayout>  
  26.   
  27. </FrameLayout></span>  
item01.xml源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;"><?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.       
  7.     <ImageView    
  8.         android:layout_width="fill_parent"    
  9.         android:layout_height="fill_parent"    
  10.         android:background="@drawable/feature_guide_0" >    
  11.     </ImageView>  
  12.       
  13. </LinearLayout></span>  
其中item02.xml,item03.xml,item04.xml布局文件的源码和item01.xml布局文件一样,只是 ImageView 中的 android:background 属性的背景图片不同而已。

GuideViewDemoActivity.java 源码:

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.guidedemo;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.app.Activity;  
  6. import android.os.Bundle;  
  7. import android.os.Parcelable;  
  8. import android.support.v4.view.PagerAdapter;  
  9. import android.support.v4.view.ViewPager;  
  10. import android.support.v4.view.ViewPager.OnPageChangeListener;  
  11. import android.view.LayoutInflater;  
  12. import android.view.View;  
  13. import android.view.ViewGroup;  
  14. import android.view.ViewGroup.LayoutParams;  
  15. import android.view.Window;  
  16. import android.widget.ImageView;  
  17.   
  18. public class GuideViewDemoActivity extends Activity {  
  19.       
  20.     private ViewPager viewPager;    
  21.     private ArrayList<View> pageViews;    
  22.     private ViewGroup main, group;    
  23.     private ImageView imageView;    
  24.     private ImageView[] imageViews;   
  25.       
  26.     /** Called when the activity is first created. */  
  27.     @Override  
  28.     public void onCreate(Bundle savedInstanceState) {  
  29.         super.onCreate(savedInstanceState);  
  30.         this.requestWindowFeature(Window.FEATURE_NO_TITLE);  
  31.           
  32.         LayoutInflater inflater = getLayoutInflater();    
  33.         pageViews = new ArrayList<View>();    
  34.         pageViews.add(inflater.inflate(R.layout.item01, null));    
  35.         pageViews.add(inflater.inflate(R.layout.item02, null));    
  36.         pageViews.add(inflater.inflate(R.layout.item03, null));    
  37.         pageViews.add(inflater.inflate(R.layout.item04, null));     
  38.     
  39.         imageViews = new ImageView[pageViews.size()];    
  40.         main = (ViewGroup)inflater.inflate(R.layout.main, null);    
  41.           
  42.         // group是R.layou.main中的负责包裹小圆点的LinearLayout.    
  43.         group = (ViewGroup)main.findViewById(R.id.viewGroup);    
  44.     
  45.         viewPager = (ViewPager)main.findViewById(R.id.guidePages);    
  46.     
  47.         for (int i = 0; i < pageViews.size(); i++) {    
  48.             imageView = new ImageView(GuideViewDemoActivity.this);    
  49.             imageView.setLayoutParams(new LayoutParams(20,20));    
  50.             imageView.setPadding(20, 0, 20, 0);    
  51.             imageViews[i] = imageView;    
  52.             if (i == 0) {    
  53.                 //默认选中第一张图片  
  54.                 imageViews[i].setBackgroundResource(R.drawable.page_indicator_focused);    
  55.             } else {    
  56.                 imageViews[i].setBackgroundResource(R.drawable.page_indicator);    
  57.             }    
  58.             group.addView(imageViews[i]);    
  59.         }    
  60.     
  61.         setContentView(main);    
  62.     
  63.         viewPager.setAdapter(new GuidePageAdapter());    
  64.         viewPager.setOnPageChangeListener(new GuidePageChangeListener());    
  65.     }  
  66.       
  67.     /** 指引页面Adapter */  
  68.     class GuidePageAdapter extends PagerAdapter {    
  69.             
  70.         @Override    
  71.         public int getCount() {    
  72.             return pageViews.size();    
  73.         }    
  74.     
  75.         @Override    
  76.         public boolean isViewFromObject(View arg0, Object arg1) {    
  77.             return arg0 == arg1;    
  78.         }    
  79.     
  80.         @Override    
  81.         public int getItemPosition(Object object) {    
  82.             // TODO Auto-generated method stub    
  83.             return super.getItemPosition(object);    
  84.         }    
  85.     
  86.         @Override    
  87.         public void destroyItem(View arg0, int arg1, Object arg2) {    
  88.             // TODO Auto-generated method stub    
  89.             ((ViewPager) arg0).removeView(pageViews.get(arg1));    
  90.         }    
  91.     
  92.         @Override    
  93.         public Object instantiateItem(View arg0, int arg1) {    
  94.             // TODO Auto-generated method stub    
  95.             ((ViewPager) arg0).addView(pageViews.get(arg1));    
  96.             return pageViews.get(arg1);    
  97.         }    
  98.     
  99.         @Override    
  100.         public void restoreState(Parcelable arg0, ClassLoader arg1) {    
  101.             // TODO Auto-generated method stub    
  102.     
  103.         }    
  104.     
  105.         @Override    
  106.         public Parcelable saveState() {    
  107.             // TODO Auto-generated method stub    
  108.             return null;    
  109.         }    
  110.     
  111.         @Override    
  112.         public void startUpdate(View arg0) {    
  113.             // TODO Auto-generated method stub    
  114.     
  115.         }    
  116.     
  117.         @Override    
  118.         public void finishUpdate(View arg0) {    
  119.             // TODO Auto-generated method stub    
  120.     
  121.         }    
  122.     }   
  123.       
  124.     /** 指引页面改监听器 */  
  125.     class GuidePageChangeListener implements OnPageChangeListener {    
  126.     
  127.         @Override    
  128.         public void onPageScrollStateChanged(int arg0) {    
  129.             // TODO Auto-generated method stub    
  130.     
  131.         }    
  132.     
  133.         @Override    
  134.         public void onPageScrolled(int arg0, float arg1, int arg2) {    
  135.             // TODO Auto-generated method stub    
  136.     
  137.         }    
  138.     
  139.         @Override    
  140.         public void onPageSelected(int arg0) {    
  141.             for (int i = 0; i < imageViews.length; i++) {    
  142.                 imageViews[arg0]    
  143.                         .setBackgroundResource(R.drawable.page_indicator_focused);    
  144.                 if (arg0 != i) {    
  145.                     imageViews[i]    
  146.                             .setBackgroundResource(R.drawable.page_indicator);    
  147.                 }    
  148.             }  
  149.     
  150.         }    
  151.     
  152.     }    
  153.       
  154. }</span>  
运行上面的程序,效果截图如下:

   
至此大功告成,已经采用ViewPager组件实现了左右滑动(拖动)效果。本文为[Andy.Chen]原创,转载请注明出处,谢谢。
该实例的源码可以在:http://download.csdn.net/detail/cjjky/4200425 点击打开链接 下载。

作者:cjjky 发表于2012-3-31 22:15:17 原文链接
阅读:3505 评论:9 查看评论

[原]设计模式之八 --- 装饰模式(Decorator)

【1】基本概念

          装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

【2】简单分析

          我们先来看下该设计模式的UML结构图


上图是Decorator 模式的结构图,让我们可以进行更方便的描述:

Component是定义一个对象接口,可以给这些对象动态地添加职责。

ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。

Decorator是装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator存在的。

ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能。

【3】如何用Java语音来实现该设计模式

假设情景:某人装扮自己形象,穿衣服,裤子,鞋子,戴帽子等来把自己给包装起来,需要把所需的功能按正确的顺序串联起来进行控制,我们应该如何设计才能做到呢?如下,先看下代码结构图:


3.1 先创建一个接口类:Component.java 

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.component;  
  2.   
  3. public interface Component {  
  4.       
  5.     void show();  
  6.   
  7. }</span>  
3.2 创建一个具体的 ConcreteComponent 来实现 Component 接口:Person.java

[html]  view plain copy print ?
  1. <span style="color:#009900;">package com.andyidea.patterns.concretecomponent;  
  2.   
  3. import com.andyidea.patterns.component.Component;  
  4.   
  5. public class Person implements Component{  
  6.       
  7.     private String name;  
  8.       
  9.     public String getName() {  
  10.         return name;  
  11.     }