Java设计模式(疯狂Java联盟版)
个人修改增强版
Java设计模式(疯狂Java联盟版)
目录
1. 设计模式 ........................................................................................................................................ 2
1.1 创建型模式 .......................................................................................................................... 3
1.1.1 工厂方法(FactoryMethod) .................................................................................. 3 1.1.2 抽象工厂(AbstractFactory) .................................................................................. 6 1.1.3 建造者模式(Builder).......................................................................................... 10 1.1.4 单态模式(Singleton) .......................................................................................... 14 1.1.5 原型模式(Prototype) ......................................................................................... 15 1.2 结构型模式 ........................................................................................................................ 18
1.2.1 适配器模式(Adapter) ........................................................................................ 18 1.2.2 桥接模式(Bridge) ............................................................................................... 20 1.2.3 组合模式(Composite) ........................................................................................ 24 1.2.4 装饰模式(Decorator) ......................................................................................... 28 1.2.5 外观模式(Facade) .............................................................................................. 30 1.2.6 享元模式(Flyweight) ....................................................................................... 33 1.2.7 代理模式(Proxy) .............................................................................................. 36 1.3 行为型模式 ........................................................................................................................ 40
1.3.1 责任链模式(Chain of Responsibility)................................................................. 40 1.3.2 命令模式(Command) ........................................................................................ 44 1.3.3 解释器模式(Interpreter) ................................................................................... 48 1.3.4 迭代器模式(Iterator) ......................................................................................... 51 1.3.5 中介者模式(Mediator) ...................................................................................... 55 1.3.6 备忘录模式(Memento) ..................................................................................... 58 1.3.7 观察者模式(Observer) ...................................................................................... 61 1.3.8 状态模式(State) ................................................................................................. 66 1.3.9 策略模式(Strategy) ............................................................................................ 68 1.3.10 模板方法(TemplateMethod) ........................................................................... 71 1.3.11 访问者模式(Visitor) ........................................................................................ 73
1
Java设计模式(疯狂Java联盟版)
1. 设计模式
内容简介
有感于设计模式在日常开发中的重要性,同时笔者也自觉对设计模式小有心得,故笔者*写二十三种设计模式的简单例子、并整理二十三种设计模式的理论部分,综合汇总成这份Java设计模式(疯狂Java联盟版),希望对大家有所帮助。
本份帮助文档主要是为了向读者介绍二十三种设计模式,包括模式的描述,适用性,模式的组成部分,并附带有简单的例子和类*,目的是为了让读者了解二十三种设计模式,并能方便的查阅各种设计模式的用法及注意点。
所附的例子非常简单,慢慢的引导读者从浅到深了解设计模式,并能从中享受设计的乐趣。
由于每个人对设计*式的理解都不尽一致,因此,可能本文档的例子*有不恰当的地方,还望各位读者指出不恰当的地方。
欢迎登录疯狂Java联盟进行技术交流,疯狂Java联盟的论坛宗旨是:
所有的技术发帖,均有回复。
疯狂Java联盟网址:http://www.crazyit.org
笔者简介
笔者曾师从李刚老师学习Java,现居广州。对Java软件开发、各种Java开源技术都非常感兴趣,曾参与开发、主持*发过大量Java、Java EE项目,对Java、Java *E项目有一定认识*见解。欢迎大家与笔者就Java、Java EE相*方面进行技术交流。
笔者现为疯狂Java联盟的总版主(论坛ID:杨恩雄),也希望通过该平台与大家分享Java、Java EE技术、*得。
本人邮箱:yangenxiong@163.com
声明
本文档编写、制作过程中得到了疯狂Java联盟、以及笔者学习工作过程大量朋友的支持,大家都抱着一个目的:为国内软件 软件开发事业作出绵薄贡献。
我们在此郑重宣布,本*档遵循Apache 2.0协议。在完整保留全部文本(包括本版权页),并且不违反Apache 2.0协议的前提
下,允许和鼓励任何人进行全文转载及推广,我们放弃除署名权外的一切权利。
2
Java设计模式(疯狂Java联盟版)
1.1 创建型模式
FactoryMethod ( 工厂方法 ) AbstractFactory ( 抽象工厂 ) Singleton ( 单态模式 ) Builder ( 建造者模式 ) Prototype ( 原型模式 )
1.1.1 工厂方法(FactoryMethod)
定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例化延迟到其子类。
适用性
1.当一个类不知道它所必须创建的对象的类的时候。
2.当一个类希望由它的子类来指定它所创建的对象的时候。
3.当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
参与者
1.Product
定义工厂方法所创建的对象的接口。
2.ConcreteProduct 实现Product接口。
3.Creator
声明工厂方法,该方法返回一个Product类型的对象*
Creator也可以定义一个工厂方法的缺省实现,它返回一个缺省的ConcreteProduct对象。
可以调用工厂方法以创建一个Product对象。
4.ConcreteCreator
重定义工厂方法以返回一个ConcreteProduct实例。
类图
3
Java设计模式(疯狂Java联盟版)
《Java与模式》中的图:
例子 product
public interface Work {
void doWork(); }
ConcreteProduct
public class StudentWork implements Work {
public void doWork() {
System.out.println(\学生做作业!\ } }
public class TeacherWork implements Work {
public void doWork() {
System.out.println(\老师审批作业!\ }
4
Java设计模式(疯狂Java联盟版)
}
Creator
public interface IWorkFactory {
Work getWork(); }
ConcreteCreator
public class StudentWorkFactory implements IWorkFactory { public Work getWork() {
return new StudentWork(); } }
public class TeacherWorkFactory implements IWorkFactory { public Work getWork() {
return new TeacherWork(); } }
Test
public class Test {
public static void main(String[] args) {
IWorkFactory studentWorkFactory = new StudentWorkFactory(); studentWorkFactory.getWork().doWork();
IWorkFactory teacherWorkFactory = new TeacherWorkFactory(); teacherWorkFactory.getWork().doWork(); } }
本人改造:
public class Test {
public static void main(String[] args) {
IWorkFactory studentWorkFactory = new StudentWorkFactory(); Work studentWork = studentWorkFactory.getWork(); studentWork.doWork();
IWorkFactory teacherWorkFactory = new TeacherWorkFactory(); Work teatherWork = teacherWorkFactory.getWork(); teatherWork.doWork(); } }
5
Java设计模式(疯狂Java联盟版)
result
学生做作业! 老师审批作业!
形象比喻:
FACTORY METHOD—请MM去麦当劳吃汉堡,不同的MM有不同的口味,要每个都记住是一件烦人的事情,我一般采用Factory Method模式,带着MM到服务员那儿,说“要一个汉堡”,具体要什么样的汉堡呢,让MM直接跟服务员说就行了。
工厂方法模式:核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
1.1.2 抽象工厂(AbstractFactory)
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
适用性
1.一个系统要独立于它的产品的创建、组合和表示时。
2.一个系统要由多个产品系列中的一个来配置时。
3.当你要强调一系列相关的产品对象的设计以便进行联合使用时。
4.当你提供一个产品类库,而只想显示它们的接口而不是实现时。
参与者
1.AbstractFactory
声明一个创建抽象产品对象的操作接口。
2.ConcreteFactory
实现创建具体产品对象的操作。
3.AbstractProduct
为一类产品对象声明一个接口。
4.ConcreteProduct
定义一个将被相应的具体工厂创建的产品*象。
6
Java设计模式(疯狂Java联盟版)
实现abstractProduct接口。
5.Client
仅使用由AbstractFactory和AbstractProduct类声明的接口
类图
《Java与模式》中的图:
例子
abstractFactory
public interface IAnimalFactory {
ICat createCat();
IDog createDog(); }
7
Java设计模式(疯狂Java联盟版)
ConcreteFactory
public class BlackAnimalFactory implements IAnimalFactory {
public ICat createCat() { return new BlackCat(); }
public IDog createDog() { return new BlackDog(); } }
public class WhiteAnimalFactory implements IAnimalFactory {
public ICat createCat() { return new WhiteCat(); }
public IDog createDog() { return new WhiteDog(); } }
AbstractProduct
public interface ICat {
void eat(); }
public interface IDog {
void eat(); }
Concreteproduct
public class BlackCat implements ICat {
public void eat() {
System.out.println(\ } }
8
Java设计模式(疯狂Java联盟版)
public class WhiteCat implements ICat {
public void eat() {
System.out.println(\ } }
public class BlackDog implements IDog {
public void eat() {
System.out.println(\ } }
public class WhiteDog implements IDog {
public void eat() {
System.out.println(\ } }
Client
public static void main(String[] args) {
IAnimalFactory blackAnimalFactory = new BlackAnimalFactory(); ICat blackCat = blackAnimalFactory.createCat(); blackCat.eat();
IDog blackDog = blackAnimalFactory.createDog(); blackDog.eat();
IAnimalFactory whiteAnimalFactory = new WhiteAnimalFactory(); ICat whiteCat = whiteAnimalFactory.createCat(); whiteCat.eat();
IDog whiteDog = whiteAnimalFactory.createDog(); whiteDog.eat(); }
result
The black cat is eating! The black dog is eating! The white cat is eating! The white dog is eating!
9
Java设计模式(疯狂Java联盟版)
形象比喻:
ABSTRACT FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory
工厂模式:客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。
1.1.3 建造者模式(Builder)
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
适用性
1.当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
2.当构造过程必须允许被构造的对象有不同的表示时。
参与者
1.Builder
为创建一个Product对象的各个部件指定抽象接口。
2.ConcreteBuilder
实现Builder的接口以构造和装配该产品的各个部件。 定义并明确它所创建的表示。 提供一个检索产品的接口。
3.Director
构造一个使用Builder接口的对象。
4.Product
表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。
包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
类图
10
Java设计模式(疯狂Java联盟版)
例子 Builder
public interface PersonBuilder {
void buildHead();
void buildBody();
void buildFoot();
Person buildPerson(); }
ConcreteBuilder
public class ManBuilder implements PersonBuilder {
Person person;
public ManBuilder() { person = new Man(); }
public void buildbody() {
person.setBody(\建造男人的身体\
11
Java设计模式(疯狂Java联盟版)
}
public void buildFoot() {
person.setFoot(\建造男人的脚\ }
public void buildHead() {
person.setHead(\建造男人的头\ }
public Person buildPerson() { return person; } }
Director
public class PersonDirector {
public Person constructPerson(PersonBuilder pb) { pb.buildHead(); pb.buildBody(); pb.buildFoot();
return pb.buildPerson(); } }
Product
public class Person {
private String head; private String body;
private String foot;
public String getHead() { return head; }
public void setHead(String head) { this.head = head; }
public String getBody() { return body; }
public void setBody(String body) { this.body = body; }
public String getFoot() {
12
Java设计模式(疯狂Java联盟版)
return foot; }
public void setFoot(String foot) { this.foot = foot; } }
public class Man extends Person { }
Test
public class Test{
public static void main(String[] args) {
PersonDirector pd = new PersonDirector();
Person person = pd.constructPerson(new ManBuilder()); System.out.println(person.getBody()); System.out.println(person.getFoot()); System.out.println(person.getHead()); } }
result
建造男人的身体 建造男人的脚 建造男人的头
形象比喻:
BUILDER—MM最爱听的就是“我爱你”这句话了,见到不同地方的MM,要能够用她们的方言跟她说这句话哦,我有一个多种语言翻译机,上面每种语言都有一个按键,见到MM我只要按对应的键,它就能够用相应的语言说出“我爱你”这句话了,国外的MM也可以轻松搞定,这就是我的“我爱你 ”builder。(这一定比美军在伊拉克用的翻译机好卖)
建造模式:将对象的内部表象和对象的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。
13
Java设计模式(疯狂Java联盟版)
1.1.4 单态模式(Singleton)
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
适用性
1.当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
2.当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
参与者
Singleton
定义一个Instance操作,允许客户访问它的唯一实例。Instance是一个类操作。
可能负*创建它自己的唯一实例。
类图 例子 Singleton
public class Singleton {
private static Singleton sing;
private Singleton() { }
public static Singleton getInstance() { if (sing == null) {
sing = new Singleton(); }
return sing; } }
Test
public class Test {
public static void main(String[] args) {
14
Java设计模式(疯狂Java联盟版)
Singleton sing = Singleton.getInstance(); Singleton sing2 = Singleton.getInstance();
System.out.println(sing); System.out.println(sing2); } }
result
singleton.Singleton@1c78e57 singleton.Singleton@1c78e57
形象比喻:
SINGLETON—俺有6个漂亮的老婆,她们的老公都是我,我就是我们家里的老公Sigleton,她们只要说道“老公”,都是指的同一个人,那就是我(刚才做了个梦啦,哪有这么好的事)
单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用。
1.1.5 原型模式(Prototype)
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
适用性
1.当一个系统应该独立于它的产品创建、构成和表示时。
2.当要实例化的类是在运行时刻指定时,例如,通过动态装载。
3.为了避免创建一个与产品类层次平行的工厂类层次时。
4.当一个类的实例只能有几个不同状态组合中的一种时。
建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
参与者
1. Prototype
声明一个克隆自身的接口。
15
Java设计模式(疯狂Java联盟版)
2. ConcretePrototype
实现一个克隆自身的操作。
3. Client
让一个原型克隆自身从而创建一个新的对象。
类图
例子 Prototype
public class Prototype implements Cloneable {
private String name;
public void setName(String name) { this.name = name; }
public String getName() { return this.name; }
public Object clone(){ try {
return super.clone(); } catch (Exception e) { e.printStackTrace(); return null; } } }
16
Java设计模式(疯狂Java联盟版)
ConcretePrototype
public class ConcretePrototype extends Prototype {
public ConcretePrototype(String name) { setName(name); } }
Client
public class Test {
public static void main(String[] args) {
Prototype pro = new ConcretePrototype(\ Prototype pro2 = (Prototype)pro.clone(); System.out.println(pro.getName()); System.out.println(pro2.getName()); } }
result
prototype prototype
形象比喻:
PROTOTYPE—跟MM用QQ聊天,一定要说些深情的话语了,我搜集了好多肉麻的情话,需要时只要copy出来放到QQ里面就行了,这就是我的情话prototype了。(100块钱一份,你要不要)
原始模型模式:通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动态的增加或减少产品类,产品类不需要非得有任何事先确定的等级结构,原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。
17
Java设计模式(疯狂Java联盟版)
1.2 结构型模式
Adapter ( 适配器模式 ) Bridge ( 桥接模式 ) Composite ( 组合模式 ) Decorator ( 装饰模式 ) Facade ( 外观模式 ) Flyweight ( 享元模式 ) Proxy ( 代理模式 )
1.2.1 适配器模式(Adapter)
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
适用性
1.你想使用一个已经存在的类,而它的接口不符合你的需求。
2.你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
3.(仅适用于对象Adapter)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。
参与者
1.Target
定义Client使用的与特定领域相关的接口。
2.Client
与符合Target接口的对象协同。
3.Adaptee
定义一个已经存在的接口,这个接口需要适配。
4.Adapter
对Adaptee的接口与Target接口进行适配
类图
18
Java设计模式(疯狂Java联盟版)
例子 Target
public interface Target {
void adapteeMethod();
void adapterMethod(); }
Adaptee
public class Adaptee {
public void adapteeMethod() {
System.out.println(\ } }
Adapter
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) { this.adaptee = adaptee; }
public void adapteeMethod() { adaptee.adapteeMethod(); }
public void adapterMethod() { system.out.println(\ } }
Client
19
Java设计模式(疯狂Java联盟版)
2.ConcreteCommand
将一个接收者对象绑定于一个动作。
调用接收者相应的操作,以实现Execute,负责调用命令对象执行请求。
命令接口实现对象,是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
3.Client
创建一个具体命令对象并设定它的接收者。
创建具体的命令对象,并且设置命令对象的接收者。注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行。
4.Invoker
要求该命令执行这个请求。
要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
5.Receiver
知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者。
接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
类图
例子 Command
public abstract class Command {
45
Java设计模式(疯狂Java联盟版)
protected Receiver receiver;
public Command(Receiver receiver) { this.receiver = receiver; }
public abstract void execute(); }
ConcreteCommand
public class CommandImpl extends Command {
public CommandImpl(Receiver receiver) { super(receiver); }
public void execute() { receiver.request(); } }
Invoker
public class Invoker {
private Command command;
public void setCommand(Command command) { this.command = command; }
public void execute() { command.execute(); } }
Receiver
public class Receiver {
public void receive() {
System.out.println(\ } }
Test
46
Java设计模式(疯狂Java联盟版)
public class Test {
pubbic static void main(String[] args) { Receiver rec = new Receiver();
Command cmd = new CommandImpl(rec); Invoker i = new Invoker(); i.setCommand(cmd); i.execute(); } }
result
This is Receive class!
补充:
接收者Receiver才是真正的命令执行者。
形象比喻:
COMMAND—俺有一个MM家里管得特别严,没法见面,只好借助于她弟弟在我们俩之间传送信息,她对我有什么指示,就写一张纸条让她弟弟带给我。这不,她弟弟又传送过来一个COMMAND,为了感谢他,我请他吃了碗杂酱面,哪知道他说:“我同时给我姐姐三个男朋友送COMMAND,就数你最小气,才请我吃面。”
命令模式:命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。命令模式允许请求的一方和发送的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否执行,何时被执行以及是怎么被执行的。系统支持命令的撤消。
47
Java设计模式(疯狂Java联盟版)
1.3.3 解释器模式(Interpreter)
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
适用性
当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式效果最好:
1.该文法简单对于复杂的文法,文法的类层次变得庞大而无法管理。
2.效率不是一个关键问题。最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下, 转换器仍可用解释器模式实现, 该模式仍是有用的。
参与者
1.AbstractExpression(抽象表达式)
声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。
2.TerminalExpression(终结符表达式)(应该是AdvanceExpression) 实现与文法中的终结符相关联的解释操作。 一个句子中的每个终结符需要该类的一个实例。
3.NonterminalExpression(非终结符表达式) (应该是SimpleExpression) 为文法中的非终结符实现解释(Interpret)操作。
4.Context(上下文)
包含解释器之外的一些全局信息。
5.Client(客户)
构建(或被给定)表示该文法定义的语言中*个特定的句子的抽象*法树。 该抽象语法树由NonterminalExpression和TerminalExpression的实例装配而成。
调用解*操作。
类图
48
Java设计模式(疯狂Java联盟版)
例子
AbstractExpression
public abstract class Expression {
abstract void interpret(Context ctx); }
Expression
public class AdvanceExpression extends Expression {
void interpret(Context ctx) {
System.out.println(\这是高级解析器!\ } }
public class SimpleExpression extends Expression {
void interpret(Context ctx) {
System.out.println(\这是普通解析器!\ } }
Context
public class Context {
private String content;
private List list = new ArrayList();
public void setContent(String content) { this.content = content; }
49