你们好,我是小羽。面试
咱们平时使用的每个技术栈的原理或者源码都或多或少与设计模式的理念有关联,也能够这么说,只有更好的掌握了设计模式,咱们的代码编写才能更规范、简洁,效率更高。算法
其次,设计模式大多都是通过咱们的前辈的经验反复总结而成,站在巨人的肩膀上,吸取他们的经验教训,咱们的编码之路才会走的更长久。数据库
同时,在咱们的面试过程当中也是加分的选项,你若是将设计模式能跟面试官娓娓道来,面试官确定会对你另眼相看的。工做中,拥有良好的设计模式思想,对于项目的开发也会有很大的帮助。编程
接下来,跟着小羽一块儿来看看咱们须要了解的设计模式都有哪些呢~设计模式
整体来讲设计模式分为三大类:数组
_建立型模式:_工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。缓存
_结构型模式:_适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。安全
_行为型模式:_策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。数据结构
确保某一个类只有一个实例,并且自行实例化并向整个系统提供这个实例。框架
要求生成惟一序列号的环境;
在整个项目中须要一个共享访问点或共享数据,例如一个Web页面上的计数器,能够不用把每次刷新都记录到数据库中,使用单例模式保持计数器的值,并确保是线程安全的;
建立一个对象须要消耗的资源过多,如要访问IO和数据库等资源;
须要定义大量的静态常量和静态方法(如工具类)的环境,能够采用单例模式(固然,也能够直接声明为static的方式)。
线程安全:
`public class Singleton {` `private static final Singleton singleton = new Singleton();` `//限制产生多个对象` `private Singleton(){` `}` `//经过该方法得到实例对象` `public static Singleton getSingleton(){` `return singleton;` `}` `//类中其余方法,尽可能是 static` `public static void doSomething(){` `}` `}`
线程不安全:
`public class Singleton {` `private static Singleton singleton = null;` `//限制产生多个对象` `private Singleton(){` `}` `//经过该方法得到实例对象` `public static Singleton getSingleton(){` `if(singleton == null){` `singleton = new Singleton();` `}` `return singleton;` `}` `}`
针对线程不安全:
在 getSingleton 方法前加 synchronized 关键字,也能够在 getSingleton 方法内增长synchronized 来实现。
定义一个用于建立对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
jdbc 链接数据库,硬件访问,下降对象的产生和销毁
_简单工厂模式:_一个模块仅须要一个工厂类,没有必要把它产生出来,使用静态的方法
_多个工厂类:_每一个人种(具体的产品类)都对应了一个建立者,每一个建立者独立负责建立对应的产品对象,很是符合单一职责原则
_代替单例模式:_单例模式的核心要求就是在内存中只有一个对象,经过工厂方法模式也能够只在内存中生产一个对象
_延迟初始化:_ProductFactory 负责产品类对象的建立工做,而且经过 prMap 变量产生一个缓存,对须要再次被重用的对象保留
Product 为抽象产品类负责定义产品的共性,实现对事物最抽象的定义;
Creator 为抽象建立类,也就是抽象工厂,具体如何建立产品类是由具体的实现工厂 ConcreteCreator 完成的。
`public class ConcreteCreator extends Creator {` `public <T extends Product> T createProduct(Class<T> c){` `Product product=null;` `try {` `product =` `(Product)Class.forName(c.getName()).newInstance();` `} catch (Exception e) {` `//异常处理` `}` `return (T)product;` `}` `}`
为建立一组相关或相互依赖的对象提供一个接口,并且无须指定它们的具体类。
一个对象族(或是一组没有任何关系的对象)都有相同的约束。
涉及不一样操做系统的时候,均可以考虑使用抽象工厂模式。
`public abstract class AbstractCreator {` `//建立 A 产品家族` `public abstract AbstractProductA createProductA();` `//建立 B 产品家族` `public abstract AbstractProductB createProductB();` `}`
定义一个操做中的算法的框架,而将一些步骤延迟到子类中。使得子类能够不改变一个算法的结构便可重定义该算法的某些特定步骤。
多个子类有公有的方法,而且逻辑基本相同时。
重要、复杂的算法,能够把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。
重构时,模板方法模式是一个常用的模式,把相同的代码抽取到父类中,而后经过钩子函数(见“模板方法模式的扩展”)约束其行为。
抽象模板:AbstractClass
为抽象模板,它的方法分为两类:
一、基本方法:也叫作基本操做,是由子类实现的方法,而且在模板方法被调用。
二、模板方法:能够有一个或几个,通常是一个具体方法,也就是一个框架,实现对基本方法的调度,完成固定的逻辑。
注意: 为了防止恶意的操做,通常模板方法都加上 final
关键字,不容许被覆写。
_具体模板:_实现父类所定义的一个或多个抽象方法,也就是父类定义的基本方法在子类中得以实现。
`package templateMethod;` `public class TemplateMethodPattern` `{` `public static void main(String[] args)` `{` `AbstractClass tm=new ConcreteClass();` `tm.TemplateMethod();` `}` `}` `//抽象类` `abstract class AbstractClass` `{` `public void TemplateMethod() //模板方法` `{` `SpecificMethod();` `abstractMethod1();` `abstractMethod2();` `}` `public void SpecificMethod() //具体方法` `{` `System.out.println("抽象类中的具体方法被调用...");` `}` `public abstract void abstractMethod1(); //抽象方法1` `public abstract void abstractMethod2(); //抽象方法2` `}` `//具体子类` `class ConcreteClass extends AbstractClass` `{` `public void abstractMethod1()` `{` `System.out.println("抽象方法1的实现被调用...");` `}` `public void abstractMethod2()` `{` `System.out.println("抽象方法2的实现被调用...");` `}` `}`
将一个复杂对象的构建与它的表示分离,使得一样的构建过程能够建立不一样的表示。
相同的方法,不一样的执行顺序,产生不一样的事件结果时,能够采用建造者模式。
多个部件或零件,均可以装配到一个对象中,可是产生的运行结果又不相同时,则可使用该模式。
产品类很是复杂,或者产品类中的调用顺序不一样产生了不一样的效能,这个时候使用建造者模式很是合适。
_Product 产品类:_一般是实现了模板方法模式,也就是有模板方法和基本方法。
_Builder 抽象建造者:_规范产品的组建,通常是由子类实现。
_ConcreteBuilder 具体建造者:_实现抽象类定义的全部方法,而且返回一个组建好的对象。
_Director 导演类:_负责安排已有模块的顺序,而后告诉 Builder 开始建造
`public class ConcreteProduct extends Builder {` `private Product product = new Product();` `//设置产品零件` `public void setPart(){` `/*` `* 产品类内的逻辑处理` `*/` `}` `//组建一个产品` `public Product buildProduct() {` `return product;` `}` `}`
为其余对象提供一种代理以控制对这个对象的访问。
_Subject 抽象主题角色:_抽象主题类能够是抽象类也能够是接口,是一个最普通的业务类型定义,无特殊要求。
_RealSubject 具体主题角色:_也叫作被委托角色、被代理角色。它才是冤大头,是业务逻辑的具体执行者。
_Proxy 代理主题角色:_也叫作委托类、代理类。它负责对真实角色的应用,把全部抽象主题类定义的方法、限制委托给真实主题角色实现,而且在真实主题角色处理完毕先后作预处理和蔼后处理工做。
_普通代理:_在该模式下,调用者只知代理而不用知道真实的角色是谁,屏蔽了真实角色的变动对高层模块的影响,真实的主题角色想怎么修改就怎么修改,对高层次的模块没有任何的影响,只要你实现了接口所对应的方法,该模式很是适合对扩展性要求较高的场合。
_强制代理:_强制代理的概念就是要从真实角色查找到代理角色,不容许直接访问真实角色。高层模块只要调用 getProxy 就能够访问真实角色的全部方法,它根本就不须要产生一个代理出来,代理的管理已经由真实角色本身完成。
_动态代理:_根据被代理的接口生成全部的方法,也就是说给定一个接口,动态代理会宣称“我已经实现该接口下的全部方法了”。两条独立发展的线路。动态代理实现代理的职责,业务逻辑实现相关的逻辑功能,二者之间没有必然的相互耦合的关系。通知从另外一个切面切入,最终在高层模块进行耦合,完成逻辑的封装任务。
意图:横切面编程,在不改变咱们已有代码结构的状况下加强或控制对象的行为。
首要条件:被代理的类必需要实现一个接口。
`public Object getProxy(@Nullable ClassLoader classLoader) {` `if (logger.isTraceEnabled()) {` `logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());` `}` `Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);` `findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);` `return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);` `}`
用原型实例指定建立对象的种类,而且经过拷贝这些原型建立新的对象。
_资源优化场景:_类初始化须要消化很是多的资源,这个资源包括数据、硬件资源等。
_性能和安全要求的场景:_经过 new 产生一个对象须要很是繁琐的数据准备或访问权限,则可使用原型模式。
_一个对象多个修改者的场景:_一个对象须要提供给其余对象访问,并且各个调用者可能都须要修改其值时,能够、考虑使用原型模式拷贝多个对象供调用者使用。
原型模式实际上就是实现 Cloneable 接口,重写 clone()方法。
_性能优良:_原型模式是在内存二进制流的拷贝,要比直接 new 一个对象性能好不少,特别是要在一个循环体内产生大量的对象时,原型模式能够更好地体现其优势。
_逃避构造函数的约束:_这既是它的优势也是缺点,直接在内存中拷贝,构造函数是不会执行的。
`public class PrototypeClass implements Cloneable{` `//覆写父类 Object 方法` `@Override` `public PrototypeClass clone(){` `PrototypeClass prototypeClass = null;` `try {` `prototypeClass = (PrototypeClass)super.clone();` `} catch (CloneNotSupportedException e) {` `//异常处理` `}` `return prototypeClass;` `}` `}`
用一个中介对象封装一系列的对象交互,中介者使各对象不须要显示地相互做用,从而使其耦合松散,并且能够独立地改变它们之间的交互。
中介者模式适用于多个对象之间紧密耦合的状况,紧密耦合的标准是:在类图中出现了蜘蛛网状结构,即每一个类都与其余的类有直接的联系。
_Mediator 抽象中介者角色:_抽象中介者角色定义统一的接口,用于各同事角色之间的通讯。
_Concrete Mediator 具体中介者角色:_具体中介者角色经过协调各同事角色实现协做行为,所以它必须依赖于各个同事角色。
_Colleague 同事角色:_每个同事角色都知道中介者角色,并且与其余的同事角色通讯的时候,必定要经过中介者角色协做。每一个同事类的行为分为两种:一种是同事自己的行为,好比改变对象自己的状态,处理本身的行为等,这种行为叫作自发行为(SelfMethod),与其余的同事类或中介者没有任何的依赖;第二种是必须依赖中介者才能完成的行为,叫作依赖方法(Dep-Method)。
`public abstract class Mediator {` `//定义同事类` `protected ConcreteColleague1 c1;` `protected ConcreteColleague2 c2;` `//经过 getter/setter 方法把同事类注入进来` `public ConcreteColleague1 getC1() {` `return c1;` `}` `public void setC1(ConcreteColleague1 c1) {` `this.c1 = c1;` `}` `public ConcreteColleague2 getC2() {` `return c2;` `}` `public void setC2(ConcreteColleague2 c2) {` `this.c2 = c2;` `}` `//中介者模式的业务逻辑` `public abstract void doSomething1();` `public abstract void doSomething2();` `}`
将一个请求封装成一个对象,从而让你使用不一样的请求把客户端参数化,对请求排队或者记录请求日志,能够提供命令的撤销和恢复功能。
认为是命令的地方就能够采用命令模式,例如,在 GUI 开发中,一个按钮的点击是一个命令,能够采用命令模式;模拟 DOS 命令的时候,固然也要采用命令模式;触发-反馈机制的处理等。
_Receive 接收者角色:_该角色就是干活的角色,命令传递到这里是应该被执行的,具体到咱们上面的例子中就是 Group 的三个实现类(需求组,美工组,代码组)。
_Command 命令角色:_须要执行的全部命令都在这里声明。
_Invoker 调用者角色:_接收到命令,并执行命令。在例子中,我(项目经理)就是这个角色。
`public class Invoker {` `private Command command;` `// 设值注入` `public void setCommand(Command command) {` `this.command = command;` `}` `// 执行命令` `public void action() {` `this.command.execute();` `}` `}`
使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
抽象的处理者实现三个职责:
一、定义一个请求的处理方法 handleMessage,惟一对外开放的方法;
二、定义一个链的编排方法 setNext,设置下一个处理者;
三、定义了具体的请求者必须实现的两个方法:定义本身可以处理的级别getHandlerLevel 和具体的处理任务 echo。
`public abstract class Handler {` `private Handler nextHandler;` `//每一个处理者都必须对请求作出处理` `public final Response handleMessage(Request request){` `Response response = null;` `//判断是不是本身的处理级别` `if(this.getHandlerLevel().equals(request.getRequestLevel())){` `response = this.echo(request);` `}else{ //不属于本身的处理级别` `//判断是否有下一个处理者` `if(this.nextHandler != null){` `response =` `this.nextHandler.handleMessage(request);` `}else{` `//没有适当的处理者,业务自行处理` `} }` `return response;` `}` `//设置下一个处理者是谁` `public void setNext(Handler _handler){` `this.nextHandler = _handler;` `}` `//每一个处理者都有一个处理级别` `protected abstract Level getHandlerLevel();` `//每一个处理者都必须实现处理任务` `protected abstract Response echo(Request request);` `}`
链中节点数量须要控制,避免出现超长链的状况,通常的作法是在 Handler 中设置一个最大节点数量,在 setNext 方法中判断是否已是超过其阈值,超过则不容许该链创建,避免无心识地破坏系统性能。
动态地给一个对象添加一些额外的职责。就增长功能来讲,装饰模式相比生成子类更为灵活。
须要扩展一个类的功能,或给一个类增长附加功能。
须要动态地给一个对象增长功能,这些功能能够再动态地撤销。
须要为一批的兄弟类进行改装或加装功能,固然是首选装饰模式。
_Component 抽象构件:_Component 是一个接口或者是抽象类,就是定义咱们最核心的对象,也就是最原始的对象。在装饰模式中,必然有一个最基本、最核心、最原始的接口或抽象类充当Component 抽象构件。
_ConcreteComponent 具体构件:_ConcreteComponent 是最核心、最原始、最基本的接口或抽象类的实现,你要装饰的就是它。
_Decorator 装饰角色:_通常是一个抽象类,作什么用呢?实现接口或者抽象方法,它里面可不必定有抽象的方法呀,在它的属性里必然有一个 private 变量指向 Component 抽象构件。
_具体装饰角色:_两个具体的装饰类,你要把你最核心的、最原始的、最基本的东西装饰成其余东西。
`/**` `* 装饰角色` `*/` `@Data` `@AllArgsConstructor` `@NoArgsConstructor` `@Log` `class BufferedReader implements Reader{` `private Reader reader;` `@Override` `public void read() {` `reader.read();` `}` `public void readLine(){` `read();` `log.info("而且仅仅读取一行");` `}` `}`
定义一组算法,将每一个算法都封装起来,而且使它们之间能够互换。
多个类只有在算法或行为上稍有不一样的场景。
算法须要自由切换的场景。
须要屏蔽算法规则的场景。
具体策略数量超过 4 个,则须要考虑使用混合模式
_Context 封装角色:_它也叫作上下文角色,起承上启下封装做用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。
_Strategy 抽象策略角色:_策略、算法家族的抽象,一般为接口,定义每一个策略或算法必须具备的方法和属性。
_ConcreteStrategy 具体策略角色:_实现抽象策略中的操做,该类含有具体的算法。
`public enum Calculator {` `//加法运算` `ADD("+"){` `public int exec(int a,int b){` `return a+b;` `}` `},` `//减法运算` `SUB("-"){` `public int exec(int a,int b){` `return a - b;` `}` `};` `String value = "";` `//定义成员值类型` `private Calculator(String _value){` `this.value = _value;` `}` `//得到枚举成员的值` `public String getValue(){` `return this.value;` `}` `//声明一个抽象函数` `public abstract int exec(int a,int b);` `}`
将一个类的接口变换成客户端所期待的另外一种接口,从而使本来因接口不匹配而没法在一块儿工做的两个类可以在一块儿工做。
你有动机修改一个已经投产中的接口时,适配器模式多是最适合你的模式。好比系统扩展了,须要使用一个已有或新创建的类,但这个类又不符合系统的接口,怎么办?详细设计阶段不要考虑使用适配器模式,使用主要场景为扩展应用中。
_Target 目标角色:_该角色定义把其余类转换为什么种接口,也就是咱们的指望接口。
_Adaptee 源角色:_你想把谁转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象,通过适配器角色的包装,它会成为一个崭新、靓丽的角色。
_Adapter 适配器角色:_适配器模式的核心角色,其余两个角色都是已经存在的角色,而适配器角色是须要新创建的,它的职责很是简单:把源角色转换为目标角色,怎么转换?经过继承或是类关联的方式。
不使用多继承或继承的方式,而是使用直接关联,或者称为委托的方式。
对象适配器和类适配器的区别:
类适配器是类间继承,对象适配器是对象的合成关系,也能够说是类的关联关系,这是二者的根本区别。实际项目中对象适配器使用到的场景相对比较多。
`public class Adapter extends Target` `{` `private Adaptee adaptee;` `public Adapter(Adaptee adaptee)` `{` `this.adaptee=adaptee;` `}` `public void request()` `{` `adaptee.specificRequest();` `}` `}`
它提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。
_Iterator 抽象迭代器:_抽象迭代器负责定义访问和遍历元素的接口,并且基本上是有固定的 3 个方法:first()得到第一个元素,next()访问下一个元素,isDone()是否已经访问到底部(Java 叫作 hasNext()方法)。
_ConcreteIterator 具体迭代器:_具体迭代器角色要实现迭代器接口,完成容器元素的遍历。
_Aggregate 抽象容器:_容器角色负责提供建立具体迭代器角色的接口,必然提供一个相似createIterator()这样的方法,在 Java 中通常是 iterator()方法。
_Concrete Aggregate 具体容器:_具体容器实现容器接口定义的方法,建立出容纳迭代器的对象。
`/**` `* 具体迭代器` `*/` `public class ConcreteIterator<T> implements Iterator<T> {` `private List<T> list = new ArrayList<>();` `private int cursor = 0;` `public boolean hasNext() {` `return cursor != list.size();` `}` `public T next() {` `T obj = null;` `if (this.hasNext()) {` `obj = this.list.get(cursor++);` `}` `return obj;` `}` `}`
将对象组合成树形结构以表示“部分-总体”的层次结构,使得用户对单个对象和组合对象的使用具备一致性。
维护和展现部分-总体关系的场景,如树形菜单、文件和文件夹管理。
从一个总体中可以独立出部分模块或功能的场景。
只要是树形结构,就考虑使用组合模式。
Component 抽象构件角色:定义参加组合对象的共有方法和属性,能够定义一些默认的行为或属性。
_Leaf 叶子构件:_叶子对象,其下再也没有其余的分支,也就是遍历的最小单位。
_Composite 树枝构件:_树枝对象,它的做用是组合树枝节点和叶子节点造成一个树形结构。
`public class Composite extends Component {` `//构件容器` `private ArrayList<Component> componentArrayList = new` `ArrayList<Component>();` `//增长一个叶子构件或树枝构件` `public void add(Component component){` `this.componentArrayList.add(component);` `}` `//删除一个叶子构件或树枝构件` `public void remove(Component component){` `this.componentArrayList.remove(component);` `}` `//得到分支下的全部叶子构件和树枝构件` `public ArrayList<Component> getChildren(){` `return this.componentArrayList;` `}` `}`
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则全部依赖于它的对象都会获得通知并被自动更新。
关联行为场景。须要注意的是,关联行为是可拆分的,而不是“组合”关系。
事件多级触发场景。
跨系统的消息交换场景,如消息队列的处理机制。
_Subject 被观察者:_定义被观察者必须实现的职责,它必须可以动态地增长、取消观察者。它通常是抽象类或者是实现类,仅仅完成做为被观察者必须实现的职责:管理观察者并通知观察者。
_Observer 观察者:_观察者接收到消息后,即进行 update(更新方法)操做,对接收到的信息进行处理。
_ConcreteSubject 具体的被观察者:_定义被观察者本身的业务逻辑,同时定义对哪些事件进行通知。
_ConcreteObserver 具体的观察者:_每一个观察在接收到消息后的处理反应是不一样,各个观察者有本身的处理逻辑。
`public abstract class Subject {` `//定义一个观察者数组` `private Vector<Observer> obsVector = new Vector<Observer>();` `//增长一个观察者` `public void addObserver(Observer o){` `this.obsVector.add(o);` `}` `//删除一个观察者` `public void delObserver(Observer o){` `this.obsVector.remove(o);` `}` `//通知全部观察者` `public void notifyObservers(){` `for(Observer o:this.obsVector){` `o.update();` `}` `}` `}`
要求一个子系统的外部与其内部的通讯必须经过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。
为一个复杂的模块或子系统提供一个供外界访问的接口
子系统相对独立——外界对子系统的访问只要黑箱操做便可
预防低水平人员带来的风险扩散
_Facade 门面角色:_客户端能够调用这个角色的方法。此角色知晓子系统的全部功能和责任。通常状况下,本角色会将全部从客户端发来的请求委派到相应的子系统去,也就说该角色没有实际的业务逻辑,只是一个委托类。
_subsystem 子系统角色:_能够同时有一个或者多个子系统。每个子系统都不是一个单独的类,而是一个类的集合。子系统并不知道门面的存在。对于子系统而言,门面仅仅是另一个客户端而已。
`public class Client {` `//委托的子系统对象` `private A a= new A();` `private B b= new B();` `private C c= new C();` `//提供外部访问的方法` `public void methodA(){` `this.a.doSomething();` `}` `public void methodB(){` `this.b.doSomething();` `}` `public void methodC(){` `this.c.doSomething();` `}` `}`
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象以外保存这个状态。这样之后就可将该对象恢复到原先保存的状态。
须要保存和恢复数据的相关状态场景。
提供一个可回滚(rollback)的操做。
须要监控的副本场景中。
数据库链接的事务管理就是用的备忘录模式。
_Originator 发起人角色:_记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责建立和恢复备忘录数据。
_Memento 备忘录角色:_负责存储 Originator 发起人对象的内部状态,在须要的时候提供发起人须要的内部状态。
_Caretaker 备忘录管理员角色:_对备忘录进行管理、保存和提供备忘录。
`public class BeanUtils {` `//把 bean 的全部属性及数值放入到 Hashmap 中` `public static HashMap<String,Object> backupProp(Object bean){` `HashMap<String,Object> result = new` `HashMap<String,Object>();` `try {` `//得到 Bean 描述` `BeanInfo` `beanInfo=Introspector.getBeanInfo(bean.getClass());` `//得到属性描述` `PropertyDescriptor[]` `descriptors=beanInfo.getPropertyDescriptors();` `//遍历全部属性` `for(PropertyDescriptor des:descriptors){` `//属性名称` `String fieldName = des.getName();` `//读取属性的方法` `Method getter = des.getReadMethod();` `//读取属性值` `Object fieldValue=getter.invoke(bean,new` `Object[]{});` `if(!fieldName.equalsIgnoreCase("class")){` `result.put(fieldName, fieldValue);` `} } } catch (Exception e) {` `//异常处理` `}` `return result;` `}` `//把 HashMap 的值返回到 bean 中` `public static void restoreProp(Object bean,HashMap<String,Object>` `propMap){` `try {` `//得到 Bean 描述` `BeanInfo beanInfo =` `Introspector.getBeanInfo(bean.getClass());` `//得到属性描述` `PropertyDescriptor[] descriptors =` `beanInfo.getPropertyDescriptors();` `//遍历全部属性` `for(PropertyDescriptor des:descriptors){` `//属性名称` `String fieldName = des.getName();` `//若是有这个属性` `if(propMap.containsKey(fieldName)){` `//写属性的方法` `Method setter = des.getWriteMethod();` `setter.invoke(bean, new` `Object[]{propMap.get(fieldName)});` `} } } catch (Exception e) {` `//异常处理` `System.out.println("shit");` `e.printStackTrace();` `}` `}` `}`
封装一些做用于某种数据结构中的各元素的操做,它能够在不改变数据结构的前提下定义做用于这些元素的新的操做。
一个对象结构包含不少类对象,它们有不一样的接口,而你想对这些对象实施一些依赖于其具体类的操做,也就说是用迭代器模式已经不能胜任的情景。
须要对一个对象结构中的对象进行不少不一样而且不相关的操做,而你想避免让这些操做“污染”这些对象的类。
_Visitor——抽象访问者:_抽象类或者接口,声明访问者能够访问哪些元素,具体到程序中就是 visit 方法的参数定义哪些对象是能够被访问的。
_ConcreteVisitor——具体访问者:_它影响访问者访问到一个类后该怎么干,要作什么事情。
_Element——抽象元素:_接口或者抽象类,声明接受哪一类访问者访问,程序上是经过 accept 方法中的参数来定义的。
_ConcreteElement——具体元素:_实现 accept 方法,一般是 visitor.visit(this),基本上都造成了一种模式了。
_ObjectStruture——结构对象:_元素产生者,通常容纳在多个不一样类、不一样接口的容器,如 List、Set、Map 等,在项目中,通常不多抽象出这个角色。
`public class CompensationVisitor implements Visitor {` `@Override` `public void Visit(Element element) {` `// TODO Auto-generated method stub` `Employee employee = ((Employee) element);` `System.out.println(` `employee.getName() + "'s Compensation is " + (employee.getDegree() * employee.getVacationDays() * 10));` `}` `}`
当一个对象内在状态改变时容许其改变行为,这个对象看起来像改变了其类。
行为随状态改变而改变的场景,这也是状态模式的根本出发点,例如权限设计,人员的状态不一样即便执行相同的行为结果也会不一样,在这种状况下须要考虑使用状态模式。
条件、分支判断语句的替代者
_State——抽象状态角色:_接口或抽象类,负责对象状态定义,而且封装环境角色以实现状态切换。
_ConcreteState——具体状态角色:_每个具体状态必须完成两个职责:本状态的行为管理以及趋向状态处理,通俗地说,就是本状态下要作的事情,以及本状态如何过渡到其余状态。
_Context——环境角色:_定义客户端须要的接口,而且负责具体状态的切换。
`//抽象状态角色` `public abstract class State {` `//定义一个环境角色,提供子类访问` `protected Context context;` `//设置环境角色` `public void setContext(Context _context){` `this.context = _context;` `}` `//行为1` `public abstract void handle1();` `//行为2` `public abstract void handle2();` `}`
给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
重复发生的问题可使用解释器模式
一个简单语法须要解释的场景
_AbstractExpression——抽象解释器:_具体的解释任务由各个实现类完成,具体的解释器分别由TerminalExpression 和 Non-terminalExpression 完成。
_TerminalExpression——终结符表达式:_实现与文法中的元素相关联的解释操做,一般一个解释器模式中只有一个终结符表达式,但有多个实例,对应不一样的终结符。
_NonterminalExpression——非终结符表达式:_文法中的每条规则对应于一个非终结表达式,非终结符表达式根据逻辑的复杂程度而增长,原则上每一个文法规则都对应一个非终结符表达式。
_Context——环境角色:_通常是用来存放文法中各个终结符所对应的具体值,这些信息须要存放到环境角色中,不少状况下咱们使用 Map 来充当环境角色就足够了。
`/**` `* 终结符表达式` `*/` `public class TerminalExpression extends AbstractExpression {` `@Override` `public void interpret(Context ctx) {` `// 实现与语法规则中的终结符相关联的解释操做` `}` `}` `/**` `* 非终结符表达式` `*/` `public class NonterminalExpression extends AbstractExpression {` `@Override` `public void interpret(Context ctx) {` `// 实现与语法规则中的非终结符相关联的解释操做` `}` `}`
使用共享对象可有效地支持大量的细粒度的对象。
对象的信息分为两个部分:内部状态(intrinsic)与外部状态(extrinsic)。
_内部状态:_内部状态是对象可共享出来的信息,存储在享元对象内部而且不会随环境改变而改变。
_外部状态:_外部状态是对象得以依赖的一个标记,是随环境改变而改变的、不能够共享的状态。
系统中存在大量的类似对象。
细粒度的对象都具有较接近的外部状态,并且内部状态与环境无关,也就是说对象没有特定身份。
须要缓冲池的场景。
_Flyweight——抽象享元角色:_它简单地说就是一个产品的抽象类,同时定义出对象的外部状态和内部状态的接口或实现。
_ConcreteFlyweight——具体享元角色:_具体的一个产品类,实现抽象角色定义的业务。该角色中须要注意的是内部状态处理应该与环境无关,不该该出现一个操做改变了内部状态,同时修改了外部状态,这是绝对不容许的。
_unsharedConcreteFlyweight——不可共享的享元角色:_不存在外部状态或者安全要求(如线程安全)不可以使用共享技术的对象,该对象通常不会出如今享元工厂中。
_FlyweightFactory——享元工厂:_职责很是简单,就是构造一个池容器,同时提供从池中得到对象的方法。
`public class FlyweightFactory {` `//定义一个池容器` `private static HashMap<String,Flyweight> pool= new` `HashMap<String,Flyweight>();` `//享元工厂` `public static Flyweight getFlyweight(String Extrinsic){` `//须要返回的对象` `Flyweight flyweight = null;` `//在池中没有该对象` `if(pool.containsKey(Extrinsic)){` `flyweight = pool.get(Extrinsic);` `}else{` `//根据外部状态建立享元对象` `flyweight = new ConcreteFlyweight1(Extrinsic);` `//放置到池中` `pool.put(Extrinsic, flyweight);` `}` `return flyweight;` `}` `}`
将抽象和实现解耦,使得二者能够独立地变化。
不但愿或不适用使用继承的场景
接口或抽象类不稳定的场景
重用性要求较高的场景
_Abstraction——抽象化角色:_它的主要职责是定义出该角色的行为,同时保存一个对实现化角色的引用,该角色通常是抽象类。
_Implementor——实现化角色:_它是接口或者抽象类,定义角色必需的行为和属性。
_RefinedAbstraction——修正抽象化角色:_它引用实现化角色对抽象化角色进行修正。
_ConcreteImplementor——具体实现化角色:_它实现接口或抽象类定义的方法和属性。
`public abstract class Abstraction {` `//定义对实现化角色的引用` `private Implementor imp;` `//约束子类必须实现该构造函数` `public Abstraction(Implementor _imp){` `this.imp = _imp;` `}` `//自身的行为和属性` `public void request(){` `this.imp.doSomething();` `}` `//得到实现化角色` `public Implementor getImp(){` `return imp;` `}` `}`
你们在学习设计模式的时候,不要把它看得有多难,归根结底,都是一些概论性的总结。须要咱们在平时的不断学习和工做中,慢慢去理解它的深层原理,这样才能灵活应用每一种设计模式。
设计模式是在前人的总结上,对一些场景的问题的进行解决的一种方案,设计模式不是公式,不必去死记硬背每一种模式,更重要的是了解它的抽象思想,以及应用设计模式怎么更好的解决问题,能够达成什么效果。理论虽多,可是咱们要把它掌握的话,对于咱们的实际开发来讲会解决很多的问题。
固然后面还会继续为你们更新关于设计原则的内容,方便你们进一步理解设计模式。