常用设计模式

设计模式的分类:

设计模式可以分为三大类,分别是创建型设计模式、行为型设计模式以及结构型设计模式。

 

创建型的设计模式:

单例模式(Singleton)

构建模式(Builder)

原型模式(Prototype)

抽象工厂模式(Abstract Factory)

工厂方法模式(Factory Method)

 

行为设计模式:

策略模式(Strategy)

状态模式(State)

责任链模式(Chain of Responsibility)

解释器模式(Interpreter)

命令模式(Command)

观察者模式(Observer)

备忘录模式(Memento)

迭代器模式(Iterator)

模板方法模式(Template Method)

访问者模式(Visitor)

中介者模式(Mediator)

 

结构型设计模式:

装饰者模式(Decorator)

代理模式(Proxy)

组合模式(Composite)

桥连接模式(Bridge)

适配器模式(Adapter)

蝇量模式(Flyweight)

外观模式(Facade)

 

各种模式的表述:

 

单例模式(Singleton):确保有且只有一个对象被创建。

 

抽象工厂模式(Abstract Factory):允许客户创建对象的家族,而无需指定他们的具体类。

 

工厂方法模式(Factory Method):由子类决定要创建的具体类是哪一个。

 

装饰者模式(Decorator):包装一个对象,以提供新的行为。

 

状态模式(State):封装了基于状态的行为,并使用委托在行为之间切换。

 

迭代器模式(Iterator):在对象的集合之中游走,而不暴露集合的实现。

 

外观模式(Facade):简化一群类的接口。

 

策略模式(Strategy):封装可以互换的行为,并使用委托来决定要使用哪一个。

 

代理模式(Proxy):包装对象,以控制对此对象的访问。

 

适配器模式(Adapter):封装对象,并提供不同的接口。

 

观察者模式(Observer):让对象能够在状态改变时被通知。

 

模板方法模式(Template Method):有子类决定如何实现一个算法中的步骤。

 

组合模式(Composite):客户用一致的方法处理对象集合和单个对象。

 

命令模式(Command):封装请求成为对象。

 

1、装饰模式

装饰模式是对对象功能增强时,平时使用继承的一种替代方案

 

二.组成部分
1.       抽象构件:原始的功能接口
2.       具体构件:具体的原始功能类
3.       装饰角色:持有具体构件类的对象,以便执行原有功能
4.       具体装饰:具体扩展的功能在这里
三. 例子代码 : 使用装饰模式来演示一个对”行走”功能扩展的例子(听音乐+行走和唱歌+行走)
1. 抽象构件

 

       2. 具体构件

 

 

3.装饰角色来了
4.具体装饰(这里演示了两种扩展的情况,走路+听音乐和唱歌s)
(1).
(2).
5.客户端调用
四. 总结
优点:装饰模式和继承都是对功能的扩展,而装饰模式使用的是组合,可以不用继承而达到这一效果.使用过多的继承会增加系统的复杂性和偶合性
缺点:装饰模式要产生一些辅助性的对象,但这些对象看上去都比较像,不是很容易检查(好的命名应该是提高检查的一个办法)



2、单例子(Singleton)模式

 

单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。

 

一、懒汉式单例子

 
在类被加载的时候,唯一实例已经被创建。这个设计模式在Java中容易实现,在别的语言中难以实现。

 
二、饿汉式单例
 
在类加载的时候不创建单例实例。只有在第一次请求实例的时候的时候创建,并且只在第一次创建后,以后不再创建该类的实例。
 


三、登记式单例
 
登记式单例类是针对上面两种单例类不能被继承的特点而设计的。
这个单例实际上维护的是一组单例类的实例,将这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从工厂直接返回,对于没有登记的,则先登记,而后返回。
 
四、总结
单从资源利用角度来讲, 饿汉式单例类较好; 从速度和反映时间来说懒汉式单例类较好.但是, 懒汉式单例类在实例化时, 必须处理好在多线程同时首次引用此类时的访问限制问题.特别是单例类在资源控制器在实例化时必然涉及资源初始化, 而资源初始化很有可能耗费时间, 这意味着出现多线程同时引用此类的几率变得较大。
3、Composite组合模式
Composite模式是构造型的设计模式之一,通过递归手段来构造诸如文件系统之类的树形的对象结构;Composite模式所代表的数据构造是一群具有统一接口界面的对象集合,并可以通过一个对象来访问所有的对象(遍历)。

Composite模式的类图描述:

Component
树形结构的节点抽象
- 为所有的对象定义统一的接口(公共属性,行为等的定义)
- 提供管理子节点对象的接口方法
- [可选]提供管理父节点对象的接口方法

Leaf
树形结构的叶节点。Component的实现子类

Composite
树形结构的枝节点。Component的实现子类


Composite模式的应用场景
Composite模式概念起来比简单,简单一点说,可以使用Composite模式来构造一个具有统一接口界面的树形的对象群,并可通过该接口访问对象群的每个对象。


Composite模式的应用范例
我们应用Composite模式来实现文件系统的文件/目录结构:
IFile:File与Folder的共通接口界面。相当于Component。
Folder:目录。目录下面有子目录,文件。相当于Composite。
File:文件。存在于目录之中。相当于Leaf。
Client类:测试类或者说使用类。

代码:

import java.util.ArrayList;   
  1. import java.util.List;   
  2.   
  3. public class Client {   
  4.     public static void main(String[] args) {   
  5.            
  6.         //构造一个树形的文件/目录结构   
  7.         Folder rootFolder = new Folder("c://");   
  8.         Folder compositeFolder = new Folder("composite");   
  9.         rootFolder.addChild(compositeFolder);   
  10.         Folder windowsFolder = new Folder("windows");   
  11.         rootFolder.addChild(windowsFolder);   
  12.         File file = new File("TestComposite.java");   
  13.         compositeFolder.addChild(file);   
  14.            
  15.         //从rootFolder访问整个对象群   
  16.         printTree(rootFolder);   
  17.     }   
  18.        
  19.     private static void printTree(IFile ifile) {   
  20.         ifile.printName();   
  21.         List <IFile> children = ifile.getChildren();   
  22.            
  23.         for (IFile file:children) {   
  24.             if (file instanceof File) {   
  25.                 System.out.print("  ");   
  26.                 file.printName();   
  27.             } else if (file instanceof Folder) {   
  28.                 printTree(file);   
  29.             }   
  30.         }   
  31.     }   
  32.   
  33. }   
  34.   
  35.   
  36. interface IFile {   
  37.     public void printName();   
  38.        
  39.     public boolean addChild(IFile file);   
  40.     public boolean removeChild(IFile file);   
  41.     public List<IFile> getChildren();   
  42. }   
  43.   
  44. class File implements IFile {   
  45.     private String name;   
  46.        
  47.     public File(String name) {   
  48.         this.name = name;   
  49.     }   
  50.     public void printName() {   
  51.         System.out.println(name);   
  52.     }   
  53.   
  54.     public boolean addChild(IFile file) {   
  55.         return false;   
  56.     }   
  57.   
  58.     public boolean removeChild(IFile file) {   
  59.         return false;   
  60.     }   
  61.   
  62.     public List<IFile> getChildren() {   
  63.         return null;   
  64.     }   
  65.        
  66. }   
  67.   
  68. class Folder implements IFile {   
  69.     private String name;   
  70.     private List <IFile> childList;   
  71.        
  72.     public Folder(String name) {   
  73.         this.name = name;   
  74.         this.childList = new ArrayList<IFile>();   
  75.     }   
  76.     public void printName() {   
  77.         System.out.println(name);   
  78.     }   
  79.   
  80.     public boolean addChild(IFile file) {   
  81.         return childList.add(file);   
  82.     }   
  83.   
  84.     public boolean removeChild(IFile file) {   
  85.         return childList.remove(file);   
  86.     }   
  87.   
  88.     public List<IFile> getChildren() {   
  89.         return childList;   
  90.     }   
  91. }  
import java.util.ArrayList;
import java.util.List;

public class Client {
    public static void main(String[] args) {
        
        //构造一个树形的文件/目录结构
        Folder rootFolder = new Folder("c://");
        Folder compositeFolder = new Folder("composite");
        rootFolder.addChild(compositeFolder);
        Folder windowsFolder = new Folder("windows");
        rootFolder.addChild(windowsFolder);
        File file = new File("TestComposite.java");
        compositeFolder.addChild(file);
        
        //从rootFolder访问整个对象群
        printTree(rootFolder);
    }
    
    private static void printTree(IFile ifile) {
        ifile.printName();
        List <IFile> children = ifile.getChildren();
        
        for (IFile file:children) {
            if (file instanceof File) {
                System.out.print("  ");
                file.printName();
            } else if (file instanceof Folder) {
                printTree(file);
            }
        }
    }

}


interface IFile {
    public void printName();
    
    public boolean addChild(IFile file);
    public boolean removeChild(IFile file);
    public List<IFile> getChildren();
}

class File implements IFile {
    private String name;
    
    public File(String name) {
        this.name = name;
    }
    public void printName() {
        System.out.println(name);
    }

    public boolean addChild(IFile file) {
        return false;
    }

    public boolean removeChild(IFile file) {
        return false;
    }

    public List<IFile> getChildren() {
        return null;
    }
    
}

class Folder implements IFile {
    private String name;
    private List <IFile> childList;
    
    public Folder(String name) {
        this.name = name;
        this.childList = new ArrayList<IFile>();
    }
    public void printName() {
        System.out.println(name);
    }

    public boolean addChild(IFile file) {
        return childList.add(file);
    }

    public boolean removeChild(IFile file) {
        return childList.remove(file);
    }

    public List<IFile> getChildren() {
        return childList;
    }
}


执行Client,输出结果:

C:/Composite>javac *.java
C:/Composite>java Client
c:/
composite
  TestComposite.java
windows
C:/Composite>
4、工厂模式

简单工厂模式

1. 目的 
        工厂模式就是专门负责将大量有共同接口的类实例化,而且不必事先知道每次是要实例化哪一个类的模式。它定义一个用于创建对象的接口,由子类决定实例化哪一个类。
2 . 简单工厂模式的结构 
 http://zhupan.javaeye.com/upload/picture/pic/2305/0e1d5f00-1c49-4e5f-9c2c-986d989217bd.gif

3. 一个简单例子
java 代码
  1. // 产品接口         
  2. public interface Product {   
  3.   
  4.     public void getName();   
  5.   
  6. }   
  7.   
  8. // 具体产品A   
  9. public class ProductA implements Product {   
  10.   
  11.     public void getName() {   
  12.         System.out.println("  I am ProductA  ");   
  13.     }   
  14.   
  15. }   
  16.   
  17. // 具体产品B   
  18. public class ProductB implements Product {   
  19.   
  20.     public void getName() {   
  21.         System.out.println("  I am ProductB  ");   
  22.     }   
  23.   
  24. }   
  25.   
  26. // 工厂类   
  27. public class ProductCreator {   
  28.   
  29.     public Product createProduct(String type) {   
  30.         if (" A ".equals(type)) {   
  31.             return new ProductA();   
  32.         }   
  33.         if (" B ".equals(type)) {   
  34.             return new ProductB();   
  35.         } else  
  36.             return null;   
  37.     }   
  38.   
  39.     public static void main(String[] args) {   
  40.         ProductCreator creator = new ProductCreator();   
  41.         creator.createProduct(" A ").getName();   
  42.         creator.createProduct(" B ").getName();   
  43.     }   
  44. }  
4. 小结工厂模式的适用范围
• 在编码时不能预见需要创建哪一种类的实例。
• 一个类使用它的子类来创建对象。
• 开发人员不希望创建了哪个类的实例以及如何创建实例的信息暴露给外部程序。  

 

抽象工厂模式 

1. 抽象工厂模式可以说是简单工厂模式的扩展,它们主要的区别在于需要创建对象的复杂程度上。
在抽象工厂模式中,抽象产品可能是一个或多个,从而构成一个或多个产品族。 在只有一个产品族的情况下,抽象工厂模式实际上退化到工厂方法模式。
2. 抽象工厂模式的结构 

 http://zhupan.javaeye.com/upload/picture/pic/2304/aa2dfa0b-cd37-4bfc-a411-dd75ee60ab5f.gif

3. 一个简单例子

java 代码
  1. //  产品 Plant接口         
  2. public interface Plant {   
  3. }   
  4.   
  5. // 具体产品PlantA,PlantB   
  6. public class PlantA implements Plant {   
  7.   
  8.     public PlantA() {   
  9.         System.out.println(" create PlantA ! ");   
  10.     }   
  11.   
  12.     public void doSomething() {   
  13.         System.out.println("  PlantA do something  ");   
  14.     }   
  15. }   
  16.   
  17. public class PlantB implements Plant {   
  18.     public PlantB() {   
  19.         System.out.println(" create PlantB ! ");   
  20.     }   
  21.   
  22.     public void doSomething() {   
  23.         System.out.println("  PlantB do something  ");   
  24.     }   
  25. }   
  26.   
  27. // 产品 Fruit接口   
  28. public interface Fruit {   
  29. }   
  30.   
  31. // 具体产品FruitA,FruitB   
  32. public class FruitA implements Fruit {   
  33.     public FruitA() {   
  34.         System.out.println(" create FruitA ! ");   
  35.     }   
  36.   
  37.     public void doSomething() {   
  38.         System.out.println("  FruitA do something  ");   
  39.     }   
  40. }   
  41.   
  42. public class FruitB implements Fruit {   
  43.     public FruitB() {   
  44.         System.out.println(" create FruitB ! ");   
  45.     }   
  46.   
  47.     public void doSomething() {   
  48.         System.out.println("  FruitB do something  ");   
  49.     }   
  50. }   
  51.   
  52. // 抽象工厂方法   
  53. public interface AbstractFactory {   
  54.     public Plant createPlant();   
  55.   
  56.     public Fruit createFruit();   
  57. }   
  58.   
  59. // 具体工厂方法   
  60. public class FactoryA implements AbstractFactory {   
  61.     public Plant createPlant() {   
  62.         return new PlantA();   
  63.     }   
  64.   
  65.     public Fruit createFruit() {   
  66.         return new FruitA();   
  67.     }   
  68. }   
  69.   
  70. public class FactoryB implements AbstractFactory {   
  71.     public Plant createPlant() {   
  72.         return new PlantB();   
  73.     }   
  74.   
  75.     public Fruit createFruit() {   
  76.         return new FruitB();   
  77.     }   
  78. }  
4. 小结
在以下情况下,应当考虑使用抽象工厂模式。
  首先,一个系统应当不依赖于产品类实例被创立,组成,和表示的细节。这对于所有形态的工厂模式都是重要的。
  其次,这个系统的产品有多于一个的产品族。
  第三,同属于同一个产品族的产品是设计成在一起使用的。这一约束必须得在系统的设计中体现出来。
  最后,不同的产品以一系列的接口的面貌出现,从而使系统不依赖于接口实现的细节。
  其中第二丶第三个条件是我们选用抽象工厂模式而非其它形态的工厂模式的关键性条件。
5、观察者模式
 

下面的程序模仿上面的情形,一个随机数产生对象和两个观察者,这两个观察者都在随机数产生对象那里注册了,意思说如果你产生了新的数字,就通知我一声。

 

结构图:

 

类说明
 名称 功能说明
 Observer 表示观察者的接口,要成为观察者必须实现此接口才行
 NumberGenerator 表示产生数值的抽象类
 RandomNumberGenerator 产生随机数的类,继承于NumberGenerator
 NumberObserver 数字观察者,会打印出变化的数字
 SymbolObserver 符号观察者,打印N 个符号,打印多少个符号,由接受到的数值确定

 

 

 

1.Observer

Java代码 复制代码
  1. package com.pattern.observer;   
  2.   
  3. public interface Observer {   
  4.     public abstract void update(NumberGenerator generator);   
  5. }  
package com.pattern.observer;

public interface Observer {
	public abstract void update(NumberGenerator generator);
}

2.NumberGenerator

 

Java代码 复制代码
  1. package com.pattern.observer;   
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.Iterator;   
  5.   
  6. /**  
  7.  * @project JavaPattern  
  8.  * @author sunnylocus     
  9.  * @verson 1.0.0  
  10.  * @date   Aug 27, 2008 1:35:34 PM  
  11.  * @description 产生数值的抽象类  
  12.  */  
  13. public abstract class NumberGenerator {   
  14.     private ArrayList observers = new ArrayList();  //存储Observer   
  15.     /** 添加观察者*/  
  16.     public void addObserver(Observer observer) {   
  17.         observers.add(observer);   
  18.     }   
  19.     /** 删除观察者*/  
  20.     public void delObserver(Observer observer) {   
  21.         observers.remove(observer);   
  22.     }   
  23.     /** 通知所有观察者*/  
  24.     public void notifyObservers() {   
  25.         Iterator it = observers.iterator();   
  26.         while(it.hasNext()) {   
  27.             Observer o =(Observer) it.next();   
  28.             o.update(this);//this相当于上面提到的邮局名   
  29.         }   
  30.     }   
  31.     public abstract int getNumber();//获取数字   
  32.     public abstract void generate();//产生数字   
  33. }  
package com.pattern.observer;

import java.util.ArrayList;
import java.util.Iterator;

/**
 * @project JavaPattern
 * @author sunnylocus	
 * @verson 1.0.0
 * @date   Aug 27, 2008 1:35:34 PM
 * @description 产生数值的抽象类
 */
public abstract class NumberGenerator {
	private ArrayList observers = new ArrayList();  //存储Observer
	/** 添加观察者*/
	public void addObserver(Observer observer) {
		observers.add(observer);
	}
	/** 删除观察者*/
	public void delObserver(Observer observer) {
		observers.remove(observer);
	}
	/** 通知所有观察者*/
	public void notifyObservers() {
		Iterator it = observers.iterator();
		while(it.hasNext()) {
			Observer o =(Observer) it.next();
			o.update(this);//this相当于上面提到的邮局名
		}
	}
	public abstract int getNumber();//获取数字
	public abstract void generate();//产生数字
}

 

3.RandomNumberGenerator

Java代码 复制代码
  1. package com.pattern.observer;   
  2.   
  3. import java.util.Random;   
  4.   
  5. /**  
  6.  * @project JavaPattern  
  7.  * @author sunnylocus     
  8.  * @verson 1.0.0  
  9.  * @date   Aug 27, 2008 1:48:03 PM  
  10.  * @description 用于产生随机数及通知观察者的类  
  11.  */  
  12. public class RandomNumberGenerator extends NumberGenerator{   
  13.     private Random random = new Random();//随机数产生器   
  14.     private int number;   //用于存放数字   
  15.   
  16.     public void generate() {   
  17.         for(int i=0 ; i < 5; i++) {   
  18.             number = random.nextInt(10);//产生10以内的随机数   
  19.             notifyObservers();  //有新产生的数字,通知所有注册的观察者   
  20.         }   
  21.     }   
  22.     /** 获得数字*/  
  23.     public int getNumber() {   
  24.         return number;   
  25.     }   
  26.        
  27. }  
package com.pattern.observer;

import java.util.Random;

/**
 * @project JavaPattern
 * @author sunnylocus	
 * @verson 1.0.0
 * @date   Aug 27, 2008 1:48:03 PM
 * @description 用于产生随机数及通知观察者的类
 */
public class RandomNumberGenerator extends NumberGenerator{
	private Random random = new Random();//随机数产生器
	private int number;   //用于存放数字

	public void generate() {
		for(int i=0 ; i < 5; i++) {
			number = random.nextInt(10);//产生10以内的随机数
			notifyObservers();  //有新产生的数字,通知所有注册的观察者
		}
	}
    /** 获得数字*/
	public int getNumber() {
		return number;
	}
	
}

 

4.NumberObserver

Java代码 复制代码
  1. package com.pattern.observer;   
  2.   
  3. /** 以数字表示观察者的类*/  
  4. public class NumberObserver implements Observer{   
  5.     public void update(NumberGenerator generator) {   
  6.         System.out.println("NumberObserver:"+ generator.getNumber());   
  7.         try {   
  8.             Thread.sleep(1000 * 3); //为了能清楚的看到输出,休眠3秒钟。   
  9.         }catch(InterruptedException e) {   
  10.             e.printStackTrace();   
  11.         }   
  12.     }   
  13.        
  14. }  
package com.pattern.observer;

/** 以数字表示观察者的类*/
public class NumberObserver implements Observer{
	public void update(NumberGenerator generator) {
		System.out.println("NumberObserver:"+ generator.getNumber());
		try {
			Thread.sleep(1000 * 3); //为了能清楚的看到输出,休眠3秒钟。
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
	
}

 

5.SymbolObserver

Java代码 复制代码
  1. package com.pattern.observer;   
  2.   
  3. /** 以符号表示观察者的类*/  
  4. public class SymbolObserver implements Observer{   
  5.     public void update(NumberGenerator generator) {   
  6.         System.out.print("SymbolObserver:");   
  7.         int count = generator.getNumber();   
  8.            
  9.         for(int i = 0 ; i < count; i ++) {   
  10.             System.out.print("*^_^*  ");   
  11.         }   
  12.         System.out.println("");   
  13.         try {   
  14.             Thread.sleep(1000 * 3);   
  15.         }catch(InterruptedException e){   
  16.             e.printStackTrace();   
  17.         }   
  18.     }   
  19. }  
package com.pattern.observer;

/** 以符号表示观察者的类*/
public class SymbolObserver implements Observer{
	public void update(NumberGenerator generator) {
		System.out.print("SymbolObserver:");
		int count = generator.getNumber();
		
		for(int i = 0 ; i < count; i ++) {
			System.out.print("*^_^*  ");
		}
		System.out.println("");
		try {
			Thread.sleep(1000 * 3);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	}
}

 

6.Main(测试类)

Java代码 复制代码
  1. package com.pattern.observer;   
  2.   
  3. public class Main {   
  4.     public static void main(String[] args) {   
  5.         //实例化数字产生对象   
  6.         NumberGenerator generator = new RandomNumberGenerator();   
  7.         //实例化观察者   
  8.         Observer observer1 = new NumberObserver();   
  9.         Observer observer2 = new SymbolObserver();   
  10.         //注册观察者   
  11.         generator.addObserver(observer1);   
  12.         generator.addObserver(observer2);   
  13.            
  14.         generator.generate(); //产生数字   
  15.     }   
  16. }  

设计思想:

     观察者模式定义了对象之间的一对多的依赖关系,当一个对象的状态发生改变时,所有它的依赖对象将被自动通知并更新

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值