【笔记】简单整理23种设计模式及实例使用
2017-01-17 23:03
453 查看
虽然一直都在用到设计模式,但是自己对设计模式却没有去了解过,终于抽空了解并整理了一下,记录便于记忆。
2、抽象不应该依赖细节;
3、细节应该依赖抽象;
创建型模式(5种):
工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式(7种):
适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式(11种):
策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
优点:
1、良好的封装性,代码结构清晰;
2、扩展性好;
3、屏蔽产品类;
4、符合迪米特法则、依赖倒置原则和里氏替换原则,是典型的解耦框架;
使用场景:
1、有大量产品需要创建,并且具有共同接口,可以通过工厂方法模式创建;
2、需要灵活的、可扩展的框架时;
实例:
为创建一组相关或相互依赖的对象提供一个接口,而且无须制定他们的具体类。
优点:
1、抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建,可实现;
2、当一个产品族中的多个对象被设计成一起工作时,能保证客户端始终只使用同一个产品族中对象;
3、增加新的具体工厂和产品族,无须修改已有系统,符合“开闭原则”;
使用场景:
1、一个产品族都有相同的约束;
实例:
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
优点:
1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销;
2、省去new操作符,降低了系统内存的使用频率,减轻GC压力;
3、有些类创建多个,系统可能混乱。如交易所只有使用单例才能保证核心交易服务器独立控制整个交易流程;
使用场景:
1、创建某个类需要消耗大量资源;
2、某个类占用很多内存,创建太多会导致内存占用太多;
实例:
将一个复杂的对象的构造与它的表示分离,使得同样的构造过程可以创建不同的表示。
优点:
1、封装性,是客户端不必知道产品内部组成的细节;
2、独立性好,容易扩展,同时可对建造过程进行细化;
使用场景:
1、相同方法或相同属性,不同顺序会产生不同结果;
实例:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
优点:
1、性能优良;
2、避免构造函数的约束;
使用场景:
1、资源优化场景,类的初始化需要使用较多资源;
2、性能和安全要求的场景,通过new产生一个对象需要非常繁琐的数据准备或访问权限;
3、一个对象多个修改者的场景,一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时;
实例:
将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
优点:
1、让两个没有任何关系的类在一起运行;
2、增加类的透明性;
3、提高了类的复用度;
4、灵活性非常好;
使用场景:
1、想修改一个已经在使用中的接口;
实例:
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
优点:
1、装饰类和被装饰类可以独立发展,而不会互相耦合;
2、是继承关系的一个替代方案;
3、可以动态地扩展一个实现类的功能;
使用场景:
1、需要扩展一个类的功能,或给一个类增加附加功能;
2、需要动态给一个对象增加功能,这些功能可以再动态地撤销;
3、需要为一批兄弟类进行改装或加装功能,首选装饰模式;
实例:
为其他对象提供一种代理以控制对这个对象的访问。
优点:
1、职责清晰;
2、高扩展性;
3、智能化;
使用场景:
1、需要对原有方法进行修改,又不违反“对拓展开放,对修改关闭”原则;
实例:
要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行,该模式提供一个高层次的接口使得子系统更易于使用。
优点:
1、减少系统的相互依赖;
2、提高了灵活性;
3、提高了安全性;
使用场景:
1、为一个复杂的模块或子系统提供一个供外部访问的接口;
2、子系统相对独立;
3、预防低水平人员带来的风险扩散;
实例:
将抽象和实现解耦,使得两者可以独立地变化。
优点:
1、抽象和实现分离;
2、优秀的扩充能力;
3、实现细节对客户透明;
使用场景:
1、不希望或不适用使用继承的场景;
2、接口或抽象类不稳定的场景;
3、重要性要求较高的场景;
实例:
将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
优点:
1、高层模块调用简单,高层模块不必关心自己处理的是单个对象还是整个组合结构,简化了高层模块的代码;
2、节点自由增加,符合开闭原则,对后期维护非常有利;
使用场景:
1、将多个对象组合在一起进行操作,常用于表示树形结构中,例如二叉树,数等;
2、从一个整体中能独立出部分模块或功能的场景;
实例:
使用共享对象可有效地支持大量的细粒度的对象。
优点:
1、可以大大减少应用程序创建的对象,降低程序内存的占用,增强程序性能;
使用场景:
1、系统中存在大量相似对象;
2、细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关;
3、需要缓冲池的场景;
实例:
定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。
优点:
1、策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为;
2、使用策略模式可以避免使用多重条件转移语句;
使用场景:
1、对外提供算法可以自由切换的策略;
2、避免使用多重条件判断;
3、扩展性好,在现有策略上增加新策略不需要改变原有方法;
实例:
定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
优点:
1、封装不变部分,扩展可变部分;
2、提取公共部分代码,便于维护;
3、行为由父类控制,子类实现;
使用场景:
1、多个子类有公有的方法,并且逻辑基本相同时;
2、重要、复杂的算法,可以办核心算法设计成模版方法,周边相关细节由子类实现;
3、需要使用重构的地方;
实例:
定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
优点:
1、可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色;
2、在观察目标和观察者之间建立一个抽象的耦合;
3、支持广播通信;
4、符合“开闭原则”的要求;
使用场景:
1、凡是涉及到一对一或者一对多的对象交互场景都可以使用观察者模式;
实例:
它提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节。
使用场景:
1、目前已经是一个没落的模式,基本没人会单独写一个迭代器,除非是产品性质的开发(JAVA最好直接用Iterator);
实例:
使多个对象都有机会处理请求,从而避免请求的发送者和接受者直接的耦合关系,将这些对象连成一条链,并沿这条链传递该请求,直到有对象处理它为止。
优点:
1、解耦提高灵活性,责任链模式可以实现,在隐瞒客户端的情况下,对系统进行动态的调整;
实例:
将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销和恢复的操作。
优点:
1、将命令发送者和命令执行者相互解耦;
2、可扩展性,新的命令很容易加入系统;
使用场景:
1、只要是命令的地方都可以;
2、系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互;
实例:
在不破坏封闭的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,以后可将对象恢复到原先保存的状态中。
优点:
1、存储一份状态,可用于回滚;
使用场景:
1、需要保存和恢复数据的相关状态场景;
实例:
当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。
优点:
1、结构清晰,避免了switch...case或if...else使用,避免了程序的复杂程度,提高系统可维护性;
2、遵循设计原则,体现开闭原则和单一职责原则,每个状态都是一个类,增加或改变状态都只要修改一个子类;
3、封装性好,状态变换放置在类内部,外部调用不用知道内部状态和行为变换;
使用场景:
1、行为随状态改变而改变的场景;
2、条件、分支判断语句的替代者;
实例:
封装一个作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新操作。
优点:
1、符合单一职责原则;
2、优秀的扩展性;
3、灵活性非常高;
使用场景:
1、一个对象结构包含很多类对象,它们有不同接口,而你想对这些对象实施一些依赖于其具体类的操作,也就是迭代器模式已经不能胜任的情景;
2、需要对一个对象结构中的对象进行很多不同并且不相关的操作,而你想避免让这些操作“污染”这些对象的类;
(使用率不高,大部分情况不需要访问者模式,少数特定场景需要)
实例:
用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
优点:
1、减少类间依赖,把原有的一对多的依赖变成一对一的依赖,同事类只依赖中介者,减少了依赖,当然同时也降低了类间的耦合;
使用场景:
1、适用于多个对象之间紧密耦合的情况,紧密耦合的标准是:在类图中出现蜘蛛网状结构。
实例:
给定一门语言,定义它的文法的一种表示,并定义一个解释器,这个解释器用于解析语言。
优点:
1、扩展性,修改语法规则只要修改相应的非终结符表达式即可;
使用场景:
1、重复发生的问题可以使用解释其模式;
2、一个简单语法需要解释的场景;
一、设计模式的六大原则
单一职责原则
应该有且仅有一个原因引起类的变更。里氏替换原则
所有引用基类的地方必须能透明地使用其子类的对象。开闭原则
一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。依赖倒置原则
1、层模块不应该依赖底层模块,两者都应该依赖其抽象;2、抽象不应该依赖细节;
3、细节应该依赖抽象;
接口隔离原则
类间的依赖关系应该建立在最小的接口上。迪米特法则
也可以说最少知道原则。一个对象应该对其他对象有最少的了解。二、23种设计模式
设计模式可分为三大类:创建型模式(5种):
工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式(7种):
适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式(11种):
策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
1、创建型模式
工厂方法模式(Factory Method)
定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
优点:
1、良好的封装性,代码结构清晰;
2、扩展性好;
3、屏蔽产品类;
4、符合迪米特法则、依赖倒置原则和里氏替换原则,是典型的解耦框架;
使用场景:
1、有大量产品需要创建,并且具有共同接口,可以通过工厂方法模式创建;
2、需要灵活的、可扩展的框架时;
实例:
//产品接口 public interface Product { String getProductType(); } //产品A public class ProductA implements Product { @Override public String getProductType() { return "ProductA"; } } //产品B public class ProductB implements Product { @Override public String getProductType() { return "ProductB"; } } //简单使用 Product product = Factory.createProductA(); product.getProductType();
抽象工厂模式(Abstract Factory)
定义:为创建一组相关或相互依赖的对象提供一个接口,而且无须制定他们的具体类。
优点:
1、抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建,可实现;
2、当一个产品族中的多个对象被设计成一起工作时,能保证客户端始终只使用同一个产品族中对象;
3、增加新的具体工厂和产品族,无须修改已有系统,符合“开闭原则”;
使用场景:
1、一个产品族都有相同的约束;
实例:
//产品A抽象 public abstract class AbstractProductA { abstract String getProductAType(); } //产品A1 public class AbstractProductA1 extends AbstractProductA { @Override String getProductAType() { return "AbstractProductA1"; } } //产品A2 public class AbstractProductA2 extends AbstractProductA { @Override String getProductAType() { return "AbstractProductA2"; } } //产品B抽象 public abstract class AbstractProductB { abstract String getProductBType(); } //产品B1 public class AbstractProductB1 extends AbstractProductB { @Override String getProductBType() { return "AbstractProductB1"; } } //产品B2 public class AbstractProductB2 extends AbstractProductB { @Override String getProductBType() { return "AbstractProductB2"; } } //工厂抽象 public abstract class AbstractFactory { abstract AbstractProductA createProductA(); abstract AbstractProductB createProductB(); } //工厂1生产1号产品 public class AbstractFactory1 extends AbstractFactory { @Override AbstractProductA createProductA() { return new AbstractProductA1(); } @Override AbstractProductB createProductB() { return new AbstractProductB1(); } } //工厂2生产2号产品 public class AbstractFactory2 extends AbstractFactory { @Override AbstractProductA createProductA() { return new AbstractProductA2(); } @Override AbstractProductB createProductB() { return new AbstractProductB2(); } } //简单使用 AbstractFactory abstractFactory = new AbstractFactory1(); AbstractProductA abstractProductA = abstractFactory.createProductA(); AbstractProductB abstractProductB = abstractFactory.createProductB(); abstractProductA.getProductAType(); abstractProductB.getProductBType();
单例模式(Singleton)
定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
优点:
1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销;
2、省去new操作符,降低了系统内存的使用频率,减轻GC压力;
3、有些类创建多个,系统可能混乱。如交易所只有使用单例才能保证核心交易服务器独立控制整个交易流程;
使用场景:
1、创建某个类需要消耗大量资源;
2、某个类占用很多内存,创建太多会导致内存占用太多;
实例:
public class Singleton { private static Singleton instance; //将默认的构造函数私有化,防止其他类手动new对象 private Singleton() { } public static Singleton getInstance() { if (instance == null) { //避免不必要的同步 synchronized (Singleton.class) { if (instance == null) { //确保没有其他线程进入过synchronized块创建实例 instance = new Singleton(); } } } return instance; } }
建造者模式(Builder)
定义:将一个复杂的对象的构造与它的表示分离,使得同样的构造过程可以创建不同的表示。
优点:
1、封装性,是客户端不必知道产品内部组成的细节;
2、独立性好,容易扩展,同时可对建造过程进行细化;
使用场景:
1、相同方法或相同属性,不同顺序会产生不同结果;
实例:
//简单对象 public class MyData { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } //建造者 public static class MyBuilder { private int id; private String name; public MyData build() { MyData myData = new MyData(); myData.setId(id); myData.setName(name); return myData; } public MyBuilder setId(int id) { this.id = id; return this; } public MyBuilder setName(String name) { this.name = name; return this; } } } //简单使用 MyData myData = new MyData.MyBuilder().setId(1).setName("SJL").build();
原型模式(Prototype)
定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
优点:
1、性能优良;
2、避免构造函数的约束;
使用场景:
1、资源优化场景,类的初始化需要使用较多资源;
2、性能和安全要求的场景,通过new产生一个对象需要非常繁琐的数据准备或访问权限;
3、一个对象多个修改者的场景,一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时;
实例:
//简单实现 public class MyPrototype implements Cloneable { private int id; private String name; public MyPrototype(int id, String name) { this.id = id; this.name = name; } @Override protected Object clone() throws CloneNotSupportedException { return new MyPrototype(id,name); } }
2、结构型模式
适配器模式(Adapter)
定义:将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
优点:
1、让两个没有任何关系的类在一起运行;
2、增加类的透明性;
3、提高了类的复用度;
4、灵活性非常好;
使用场景:
1、想修改一个已经在使用中的接口;
实例:
//原有方法 public class Source { public void method1(){ System.out.println("method1"); } } //目标接口 public interface ITarget { void method1(); void method2(); } //类适配器 public class Adapter1 extends Source implements ITarget { @Override public void method2() { System.out.println("method2"); } } //对象适配器 public class Adapter2 implements ITarget { private Source source; public Adapter2(Source source) { this.source = source; } @Override public void method1() { source.method1(); } @Override public void method2() { System.out.println("method2"); } } //接口适配器 public class Adapter3 implements ITarget { @Override public void method1() { System.out.println("method1"); } @Override public void method2() { } } //接口适配器继承类 public class Adapter3Extends extends Adapter3 { @Override public void method2() { super.method2(); System.out.println("method2"); } } //简单使用 //类适配 ITarget iTarget1 = new Adapter1(); iTarget1.method1(); iTarget1.method2(); //对象适配 ITarget iTarget2 = new Adapter2(new Source()); iTarget2.method1(); iTarget2.method2(); //接口适配 ITarget iTarget3 = new Adapter3Extends(); iTarget3.method1(); iTarget3.method2();
装饰模式(Decorator)
定义:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
优点:
1、装饰类和被装饰类可以独立发展,而不会互相耦合;
2、是继承关系的一个替代方案;
3、可以动态地扩展一个实现类的功能;
使用场景:
1、需要扩展一个类的功能,或给一个类增加附加功能;
2、需要动态给一个对象增加功能,这些功能可以再动态地撤销;
3、需要为一批兄弟类进行改装或加装功能,首选装饰模式;
实例:
//源接口 public interface Source { void method(); } //源实现类 public class SourceImp implements Source { @Override public void method() { System.out.println("SourceImp method"); } } //装饰类 public class Decorator implements Source { private Source source; public Decorator(Source source) { super(); this.source = source; } @Override public void method() { System.out.println("Decorator method before"); source.method(); System.out.println("Decorator method after"); } } //简单使用 Source source = new SourceImp(); Source decorator = new Decorator(source); decorator.method();
代理模式(Proxy)
定义:为其他对象提供一种代理以控制对这个对象的访问。
优点:
1、职责清晰;
2、高扩展性;
3、智能化;
使用场景:
1、需要对原有方法进行修改,又不违反“对拓展开放,对修改关闭”原则;
实例:
//目标接口 public interface Subject { void method(); } //目标实现 public class SubjectImp implements Subject { @Override public void method() { System.out.println("SubjectImp method"); } } //代理 public class Proxy implements Subject { private Subject subject; public Proxy() { this.subject = new SubjectImp(); } @Override public void method() { before(); subject.method(); after(); } private void before() { System.out.println("Proxy before"); } private void after() { System.out.println("Proxy after"); } } //简单使用 Subject subject = new Proxy(); subject.method();
外观模式(Facade)
定义:要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行,该模式提供一个高层次的接口使得子系统更易于使用。
优点:
1、减少系统的相互依赖;
2、提高了灵活性;
3、提高了安全性;
使用场景:
1、为一个复杂的模块或子系统提供一个供外部访问的接口;
2、子系统相对独立;
3、预防低水平人员带来的风险扩散;
实例:
//自动洗衣机 public class WashingMachine { public void shuixi(){ System.out.println("水洗"); } public void piaoxi(){ System.out.println("漂洗"); } public void tuoshui(){ System.out.println("脱水"); } } //自动洗衣机 public class AutomaticWashingMachine { private WashingMachine washingMachine = new WashingMachine(); public void washingClothes(){ washingMachine.shuixi(); washingMachine.piaoxi(); washingMachine.tuoshui(); } } //简单使用 AutomaticWashingMachine automaticWashingMachine = new AutomaticWashingMachine(); automaticWashingMachine.washingClothes();
桥接模式(Bridge)
定义:将抽象和实现解耦,使得两者可以独立地变化。
优点:
1、抽象和实现分离;
2、优秀的扩充能力;
3、实现细节对客户透明;
使用场景:
1、不希望或不适用使用继承的场景;
2、接口或抽象类不稳定的场景;
3、重要性要求较高的场景;
实例:
//目标接口 public interface Source { void method(); } //目标实现1 public class SourceImp1 implements Source { @Override public void method() { System.out.println("SourceImp1 method"); } } //目标实现2 public class SourceImp2 implements Source { @Override public void method() { System.out.println("SourceImp2 method"); } } //桥抽象 public abstract class Bridge implements Source { private Source source; @Override public void method() { source.method(); } public Source getSource() { return source; } public void setSource(Source source) { this.source = source; } } //自定义的桥 public class MyBridge extends Bridge { @Override public void method() { getSource().method(); } } //简单使用 Bridge bridge = new MyBridge(); //目标对象1 Source source1 = new SourceImp1(); bridge.setSource(source1); bridge.method(); //目标对象2 Source source2 = new SourceImp2(); bridge.setSource(source2); bridge.method();
组合模式(Composite)
定义:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
优点:
1、高层模块调用简单,高层模块不必关心自己处理的是单个对象还是整个组合结构,简化了高层模块的代码;
2、节点自由增加,符合开闭原则,对后期维护非常有利;
使用场景:
1、将多个对象组合在一起进行操作,常用于表示树形结构中,例如二叉树,数等;
2、从一个整体中能独立出部分模块或功能的场景;
实例:
//树 public class TreeNode { private String name; private TreeNode parent; private Vector<TreeNode> children = new Vector<TreeNode>(); public TreeNode(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public TreeNode getParent() { return parent; } public void setParent(TreeNode parent) { this.parent = parent; } //添加孩子节点 public void add(TreeNode node){ children.add(node); } //删除孩子节点 public void remove(TreeNode node){ children.remove(node); } //获得孩子节点 public Enumeration<TreeNode> getChildren(){ return children.elements(); } } //简单使用 TreeNode root = new TreeNode("root"); TreeNode children1 = new TreeNode("children1"); TreeNode children2 = new TreeNode("children2"); TreeNode children11 = new TreeNode("children11"); children1.add(children11); root.add(children1); root.add(children2);
享元模式(Flyweight)
定义:使用共享对象可有效地支持大量的细粒度的对象。
优点:
1、可以大大减少应用程序创建的对象,降低程序内存的占用,增强程序性能;
使用场景:
1、系统中存在大量相似对象;
2、细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关;
3、需要缓冲池的场景;
实例:
//数据对象抽象 public abstract class Flyweight { //内部状态 private String inState; //外部状态 protected final String outState; public Flyweight(String outState) { this.outState = outState; } public String getInState() { return inState; } public void setInState(String inState) { this.inState = inState; } abstract void operate(); } //实际数据对象1 public class FlyweightReal1 extends Flyweight { public FlyweightReal1(String outState) { super(outState); } @Override void operate() { System.out.println(outState+" operate"); } } //数据获取工厂 public class FlyweightFactory { //定义一个池容量 private static HashMap<String, Flyweight> pool = new HashMap<String, Flyweight>(); public static Flyweight getFlyweight(String outState) { //结果数据 Flyweight flyweight = null; if (pool.containsKey(outState)) { //池中有该对象,获取该对象 flyweight = pool.get(outState); } else { //池中无该对象,创建并放入池中 flyweight = new FlyweightReal1(outState); pool.put(outState, flyweight); } return flyweight; } } //简单使用 Flyweight flyweight = FlyweightFactory.getFlyweight("data1"); flyweight.operate(); flyweight = FlyweightFactory.getFlyweight("data2"); flyweight.operate(); flyweight = FlyweightFactory.getFlyweight("data1"); flyweight.operate();
3、行为型模式
策略模式(strategy)
定义:定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。
优点:
1、策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为;
2、使用策略模式可以避免使用多重条件转移语句;
使用场景:
1、对外提供算法可以自由切换的策略;
2、避免使用多重条件判断;
3、扩展性好,在现有策略上增加新策略不需要改变原有方法;
实例:
//辅助类 public abstract class AbstractCalculator { public int[] split(String exp, String opt) { String[] arrayStr = exp.split(opt); int[] arrayInt = new int[2]; arrayInt[0] = Integer.parseInt(arrayStr[0]); arrayInt[1] = Integer.parseInt(arrayStr[1]); return arrayInt; } } //算法接口 public interface ICalculator { int calculate(String str); } //- public class Minus extends AbstractCalculator implements ICalculator { @Override public int calculate(String str) { int[] arrayInt = split(str, "-"); return arrayInt[0] - arrayInt[1]; } } //+ public class Plus extends AbstractCalculator implements ICalculator { @Override public int calculate(String str) { int[] arrayInt = split(str, "\\+"); return arrayInt[0] + arrayInt[1]; } } //简单使用 ICalculator iCalculator = new Plus(); iCalculator.calculate("1+1"); iCalculator = new Minus(); iCalculator.calculate("1-1");
模板方法模式(Template Method)
定义:定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
优点:
1、封装不变部分,扩展可变部分;
2、提取公共部分代码,便于维护;
3、行为由父类控制,子类实现;
使用场景:
1、多个子类有公有的方法,并且逻辑基本相同时;
2、重要、复杂的算法,可以办核心算法设计成模版方法,周边相关细节由子类实现;
3、需要使用重构的地方;
实例:
//计算模版 public abstract class AbstractCalculator { //调用方法,实现对其他方法的调用 public final int calculator(String exp, String opt) { int[] array = split(exp, opt); return calculator(array[0], array[1]); } //子类重写的计算方法 abstract int calculator(int num1, int num2); public int[] split(String exp, String opt) { String[] arrayStr = exp.split(opt); int[] arrayInt = new int[2]; arrayInt[0] = Integer.parseInt(arrayStr[0]); arrayInt[1] = Integer.parseInt(arrayStr[1]); return arrayInt; } } //+ public class Plus extends AbstractCalculator { @Override int calculator(int num1, int num2) { return num1 + num2; } } //简单使用 AbstractCalculator calculator = new Plus(); calculator.calculator("1+2","\\+");
观察者模式(Observer)
定义:定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
优点:
1、可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色;
2、在观察目标和观察者之间建立一个抽象的耦合;
3、支持广播通信;
4、符合“开闭原则”的要求;
使用场景:
1、凡是涉及到一对一或者一对多的对象交互场景都可以使用观察者模式;
实例:
//观察者接口 public interface Observer { void update(); } //观察者1 public class ObserverImp1 implements Observer { @Override public void update() { System.out.println("ObserverImp1 update!"); } } //观察者2 public class ObserverImp2 implements Observer { @Override public void update() { System.out.println("ObserverImp2 update!"); } } //目标接口 public interface Subject { void addObserver(Observer observer); void delObserver(Observer observer); void notifyObservers(); } //目标抽象类 public abstract class AbstractSubject implements Subject { private Vector<Observer> vector = new Vector<Observer>(); @Override public void addObserver(Observer observer) { vector.add(observer); } @Override public void delObserver(Observer observer) { vector.remove(observer); } @Override public void notifyObservers() { Enumeration<Observer> enumeration = vector.elements(); while (enumeration.hasMoreElements()) { enumeration.nextElement().update(); } } //具体操作 abstract void operation(); } //目标对象 public class MySubject extends AbstractSubject { @Override void operation() { System.out.println("MySubject operation"); notifyObservers(); } } //简单使用 MySubject mySubject = new MySubject(); //添加观察者 mySubject.addObserver(new ObserverImp1()); mySubject.addObserver(new ObserverImp2()); //执行操作 mySubject.operation();
迭代器模式(Iterator)
定义:它提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节。
使用场景:
1、目前已经是一个没落的模式,基本没人会单独写一个迭代器,除非是产品性质的开发(JAVA最好直接用Iterator);
实例:
//收集器 public interface Collection { Iterator iterator(); Object get(int index); void add(Object object); int size(); } //收集齐实现类 public class CollectionImp implements Collection { private List<String> list; public CollectionImp() { list = new ArrayList<String>(); } @Override public Iterator iterator() { return new IteratorImp(this); } @Override public Object get(int index) { return list.get(index); } @Override public void add(Object object) { list.add(object.toString()); } @Override public int size() { return list.size(); } } //迭代器接口 public interface Iterator { Object next(); boolean hasNext(); } //迭代器实现类 public class IteratorImp implements Iterator { private Collection collection; private int pos = -1; public IteratorImp(Collection collection) { this.collection = collection; } @Override public Object next() { if(pos<=collection.size()){ pos++; } return collection.get(pos); } @Override public boolean hasNext() { return pos<collection.size()-1; } } //简单使用 Collection collection = new CollectionImp(); collection.add("item1"); collection.add("item2"); collection.add("item3"); //迭代 Iterator iterator = collection.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next().toString()); }
责任链模式(Chain of Responsibility)
定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者直接的耦合关系,将这些对象连成一条链,并沿这条链传递该请求,直到有对象处理它为止。
优点:
1、解耦提高灵活性,责任链模式可以实现,在隐瞒客户端的情况下,对系统进行动态的调整;
实例:
//自定义操作类接口 public interface MyHandler { void operator(); } //自定义处理类抽象 public abstract class AbstratorMyHandler { private MyHandler myHandler; public MyHandler getMyHandler() { return myHandler; } public void setMyHandler(MyHandler myHandler) { this.myHandler = myHandler; } } //自定义实现类 public class MyHandlerImp extends AbstratorMyHandler implements MyHandler { private String name; public MyHandlerImp(String name) { this.name = name; } @Override public void operator() { System.out.println(name+" operator!"); if(getMyHandler()!=null){ getMyHandler().operator(); } } } //简单使用 MyHandlerImp myHandlerImp1 = new MyHandlerImp("myHandlerImp1"); MyHandlerImp myHandlerImp2 = new MyHandlerImp("myHandlerImp2"); MyHandlerImp myHandlerImp3 = new MyHandlerImp("myHandlerImp3"); myHandlerImp1.setMyHandler(myHandlerImp2); myHandlerImp2.setMyHandler(myHandlerImp3); myHandlerImp1.operator();
命令模式(Command)
定义:将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销和恢复的操作。
优点:
1、将命令发送者和命令执行者相互解耦;
2、可扩展性,新的命令很容易加入系统;
使用场景:
1、只要是命令的地方都可以;
2、系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互;
实例:
//执行者 public interface Receiver { void doSomething(); } //执行者1 public class ReceiverImp1 implements Receiver { @Override public void doSomething() { System.out.println("ReceiverImp1 doSomething!"); } } //命令接口 public interface Command { void execute(); } //命令1 public class CommandImp1 implements Command { private Receiver receiver; public CommandImp1(Receiver receiver) { this.receiver = receiver; } @Override public void execute() { receiver.doSomething(); } } //调用者 public class Invoker { private Command command; public void setCommand(Command command) { this.command = command; } public void action() { command.execute(); } } //简单使用 //执行者 Receiver receiver = new ReceiverImp1(); //命令 Command command = new CommandImp1(receiver); //发布者 Invoker invoker = new Invoker(); //设置要发布的命令 invoker.setCommand(command); //发布 invoker.action();
备忘录模式(Memento)
定义:在不破坏封闭的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,以后可将对象恢复到原先保存的状态中。
优点:
1、存储一份状态,可用于回滚;
使用场景:
1、需要保存和恢复数据的相关状态场景;
实例:
//游戏 public class Game { private String state; public String getState() { return state; } public void setState(String state) { this.state = state; } public Memento createMemento() { return new Memento(state); } public void restoreMemento(Memento memento) { this.state = memento.getState(); } } //备份数据 public class Memento { private String state; public Memento(String state) { this.state = state; } public String getState() { return state; } public void setState(String state) { this.state = state; } } //存储 public class Storage { private Memento memento; public Storage(Memento memento) { this.memento = memento; } public Memento getMemento() { return memento; } public void setMemento(Memento memento) { this.memento = memento; } } //简单使用 //创建游戏 Game game = new Game(); game.setState("满血"); //保存进度 Storage storage = new Storage(new Memento(game.getState())); System.out.println("保存的状态:"+game.getState()); game.setState("死亡"); System.out.println("游戏后的状态:"+game.getState()); game.restoreMemento(storage.getMemento()); System.out.println("载入进度后的状态:"+game.getState());
状态模式(State)
定义:当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。
优点:
1、结构清晰,避免了switch...case或if...else使用,避免了程序的复杂程度,提高系统可维护性;
2、遵循设计原则,体现开闭原则和单一职责原则,每个状态都是一个类,增加或改变状态都只要修改一个子类;
3、封装性好,状态变换放置在类内部,外部调用不用知道内部状态和行为变换;
使用场景:
1、行为随状态改变而改变的场景;
2、条件、分支判断语句的替代者;
实例:
//电梯接口 public interface Elevator { String getFloor(); } //电梯上升 public class ElevatorUp implements Elevator { @Override public String getFloor() { return "12345"; } } //电梯下降 public class ElevatorDown implements Elevator { @Override public String getFloor() { return "54321"; } } //电梯控制接口 public interface ElevatorController { void up(); void down(); String getFloor(); } //电梯控制类 public class ElevatorControllerImp implements ElevatorController { private Elevator elevator; @Override public void up() { elevator = new ElevatorUp(); } @Override public void down() { elevator = new ElevatorDown(); } public String getFloor() { return elevator.getFloor(); } } //简单使用 ElevatorController elevatorController = new ElevatorControllerImp(); elevatorController.up(); elevatorController.getFloor(); elevatorController.down(); elevatorController.getFloor();
访问者模式(Visitor)
定义:封装一个作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新操作。
优点:
1、符合单一职责原则;
2、优秀的扩展性;
3、灵活性非常高;
使用场景:
1、一个对象结构包含很多类对象,它们有不同接口,而你想对这些对象实施一些依赖于其具体类的操作,也就是迭代器模式已经不能胜任的情景;
2、需要对一个对象结构中的对象进行很多不同并且不相关的操作,而你想避免让这些操作“污染”这些对象的类;
(使用率不高,大部分情况不需要访问者模式,少数特定场景需要)
实例:
//访问者接口 public interface Visitor { void visit(Subject subject); } //访问者实现 public class VisitorImp implements Visitor { @Override public void visit(Subject subject) { System.out.println("visit the subject:"+subject.getSubject()); } } //目标接口 public interface Subject { void accept(Visitor visitor); String getSubject(); } //目标实现 public class SubjectImp implements Subject { @Override public void accept(Visitor visitor) { visitor.visit(this); } @Override public String getSubject() { return "SubjectImp"; } } //简单使用 Subject subject = new SubjectImp(); Visitor visitor = new VisitorImp(); //访问者访问目标 subject.accept(visitor);
中介者模式(Mediator)
定义:用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
优点:
1、减少类间依赖,把原有的一对多的依赖变成一对一的依赖,同事类只依赖中介者,减少了依赖,当然同时也降低了类间的耦合;
使用场景:
1、适用于多个对象之间紧密耦合的情况,紧密耦合的标准是:在类图中出现蜘蛛网状结构。
实例:
//中介者接口 public interface Mediator { void createMediator(); void workAll(); } //中介者实现 public class MediatorImp implements Mediator { private Colleague colleague1; private Colleague colleague2; @Override public void createMediator() { colleague1 = new Colleague1(this); colleague2 = new Colleague2(this); } @Override public void workAll() { colleague1.work(); colleague2.work(); } } //同事抽象 public abstract class Colleague { private Mediator mediator; public Colleague(Mediator mediator) { this.mediator = mediator; } public Mediator getMediator() { return mediator; } abstract void work(); } //同事1 public class Colleague1 extends Colleague { public Colleague1(Mediator mediator) { super(mediator); } @Override void work() { System.out.println("Colleague1 work"); } } //同事2 public class Colleague2 extends Colleague { public Colleague2(Mediator mediator) { super(mediator); } @Override void work() { System.out.println("Colleague2 work"); } } //简单使用 Mediator mediator = new MediatorImp(); mediator.createMediator(); mediator.workAll();
解释器模式(Interpreter)
定义:给定一门语言,定义它的文法的一种表示,并定义一个解释器,这个解释器用于解析语言。
优点:
1、扩展性,修改语法规则只要修改相应的非终结符表达式即可;
使用场景:
1、重复发生的问题可以使用解释其模式;
2、一个简单语法需要解释的场景;
相关文章推荐
- Java设计模式编程中简单工厂与抽象工厂模式的使用实例
- Java技术_每天掌握一种设计模式(004)_使用场景及简单实例(创建型:抽象工厂)
- Java技术_每天掌握一种设计模式(002)_使用场景及简单实例(创建型:单例模式)
- 简单工厂模式——23种设计模式综合实例应用
- Java技术_每天掌握一种设计模式(003)_使用场景及简单实例(创建型:工厂方法)
- Java技术_每天掌握一种设计模式(005)_使用场景及简单实例(创建型:建造模式)
- 设计模式笔记1 - 简单工厂 和 工厂模式理解以及使用
- Singleton单例模式是最简单的设计模式,它的主要作用是保证在程序执行生命周期中,使用了单类模式的类仅仅能有一个实例对象存在。
- Java技术_每天掌握一种设计模式(006)_使用场景及简单实例(创建型:原型模式)
- 实例解析C#设计模式编程中简单工厂模式的使用
- 学习笔记:11种行为型设计模式简单对比
- [设计模式整理笔记 六] 工厂模式与创建者模式总结
- 23种设计模式示例(学习整理中)
- 设计模式学习笔记(1)--认识23种模式
- [设计模式整理笔记 四] 抽象工厂模式(Abstract Factory)
- 设计模式心得笔记--简单工厂
- 学习笔记:创建型设计模式简单对比
- [设计模式整理笔记 一] 基础知识
- 学习笔记:7种结构型设计模式简单对比
- [设计模式整理笔记 七] 原型模式(ProtoType)