工厂模式以及代理模式
工厂模式:
工厂模式是一种创建模式,:什么是创建,我们知道Java是面向对象的语言,那么我们想使用类中的方法以及属性,那么我们需要创建对象才能调用,那么我们我们必须:A a = new A();来创建实例,我们的工厂模式就是使用工厂来帮我们创建对象。工厂模式主要是为创建对象提供了接口:工厂模式分为3类:简单工厂 、工厂方法、抽象工厂、工厂模式我们在什么时候使用呢?
1.在编码时不能预见需要创建那种对象。
2.系统不应依赖于产品类实例如何被创建,组合、和表达的细节。
一、简单工厂模式:
这个模式很简单,使用的业务比较简单的情况下;
由3种角色组成:
工厂类角色::这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现
抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现
具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现
package com.factory.simple; /** * 水果接口 */ public interface Fruitable { // 水果的功能 void WhatIm(); }
package com.factory.simple; /** * @author :wuzhilong * @date:2018年10月25日 */ public class Apple implements Fruitable { @Override public void WhatIm() { } }
package com.factory.simple; /** * @author :wuzhilong * @date:2018年10月25日 */ public class FruitFactory { //工厂方法 public Fruitable createFruit(String type){ if("apploe".equals (type)){ return new Apple (); }else if("Pear".equals (type)){ return new Pear (); } return null; } }
工厂方法模式:
1、抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
2、具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
3、抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
4、具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
package com.factory.method; /** * 工厂接口 */ public interface FactoryInterface { Fruit createFruit(); }
package com.factory.method; /** * @author :wuzhilong * @date:2018年10月25日 * 每个产品的具体工厂 */ public class AppleFactory implements FactoryInterface { @Override public Fruit createFruit() { return new Apple (); } }
package com.factory.method; /** * @author :wuzhilong * @date:2018年10月25日 * 每个产品的具体工厂 */ public class PearFactory implements FactoryInterface { @Override public Fruit createFruit() { return new Pear (); } }
package com.factory.method; /** * @author :wuzhilong * @date:2018年10月25日 * 水果类 */ public abstract class Fruit { }
package com.factory.method; /** * @author :wuzhilong * @date:2018年10月25日 */ public class Apple extends Fruit { }
package com.factory.method; /** * @author :wuzhilong * @date:2018年10月25日 */ public class Pear extends Fruit { }
抽象工厂模式:
1.系统中有多个产品族,而系统一次只可能消费其中一族产品
2.同属于同一个产品族的产品一起使用时。
来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):
抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
package com.factory.abs; /** * 产品接口 */ public interface ThinkPadInterface { public void show(); }
package com.factory.abs; /** * @author :wuzhilong * @date:2018年10月25日 * 具体的产品 */ public class ThinkPadE implements ThinkPadInterface { @Override public void show() { } }
package com.factory.abs; /** * @author :wuzhilong * @date:2018年10月25日 * 具体的产品 */ public class ThinkPadT implements ThinkPadInterface { @Override public void show() { } }
package com.factory.abs; /** * 工厂接口 */ public interface FactoryInterface { public ThinkPadE createThinkPad(); public ThinkPadT createThinkPadE(); }
package com.factory.abs; /** * @author :wuzhilong * @date:2018年10月25日 * 工厂 */ public class Factory implements FactoryInterface{ @Override public ThinkPadE createThinkPad() { return new ThinkPadE (); } @Override public ThinkPadT createThinkPadE() { return new ThinkPadT (); } }
代理模式:
什么是代理模式:
Proxy模式又叫代理模式,是构造型的模式之一,它可以为其他对象提供一种代理(Proxy)以控制对这个对象的访问。
所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代理与被代理的目标类交互,而代理一般在交互的过程中(交互前后)进行某些特别的处理。
代理模式结构图:
代理模式的实现
代理模式可以有两种实现的方式,一种是静态代理类,另一种是各大框架都喜欢的动态代理
静态代理:
package com.wuzhilong.proxy; public interface ISinger { public void sing(); }
package com.wuzhilong.proxy; /** * 目标对象实现某一接口 */ public class Singer implements ISinger{ public void sing(){ System.out.println ("唱一首歌......"); } }
package com.wuzhilong.proxy; /** * 代理对象和目标对象实现相同接口 */ public class SingerProxy implements ISinger { //接收目标对象,来调用sing方法 private ISinger singer; public SingerProxy(ISinger singer) { this.singer = singer; } //对目标对象的sing方法进行扩展 @Override public void sing() { System.out.println ("向观众问好"); singer.sing (); System.out.println ("谢谢大家"); } }
测试:
package com.wuzhilong.proxy; /** * 静态代理模式 */ public class Demo { public static void main(String[] args) { //目标对象 ISinger iSinger = new Singer (); //代理对象 ISinger iSinger1 = new SingerProxy (iSinger); iSinger1.sing (); } }
总结:其实这里做的事情无非就是,创建一个代理类SingerProxy,继承了ISinger接口并实现了其中的方法。只不过这种实现特意包含了目标对象的方法,正是这种特征使得看起来像是“扩展”了目标对象的方法。假使代理对象中只是简单地对sing方法做了另一种实现而没有包含目标对象的方法,也就不能算作代理模式了。所以这里的包含是关键。
缺点:这种实现方式很直观也很简单,但其缺点是代理对象必须提前写出,如果接口层发生了变化,代理对象的代码也要进行维护。如果能在运行时动态地写出代理对象,不但减少了一大批代理类的代码,也少了不断维护的烦恼,不过运行时的效率必定受到影响。这种方式就是接下来的动态代理。
动态代理(JDK代理):
package com.wuzhilong.jdkproxy; public interface ISinger { public void sing(); }
package com.wuzhilong.jdkproxy; import com.wuzhilong.jdkproxy.ISinger; /** * 目标对象实现某一接口 */ public class Singer implements ISinger { public void sing(){ System.out.println ("唱一首歌......"); } }
package com.wuzhilong.jdkproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class SingerProxy implements InvocationHandler { //需要代理的真实对象 private Object subject; // 构造方法,给我们要代理的真实对象赋初值 public SingerProxy(Object subject) { this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println ("向观众问好"); // 执行目标类的方法 method.invoke (subject,args); System.out.println ("谢谢大家"); return null; } }
package com.wuzhilong.jdkproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Demo { public static void main(String[] args) throws Exception{ //代理的真实对象 ISinger singer = new Singer (); // 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的 InvocationHandler invocationHandler = new SingerProxy (singer); /* * 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数 * 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象 * 第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了 * 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上 */ ISinger singerProxy =(ISinger) Proxy.newProxyInstance (invocationHandler.getClass ().getClassLoader (),singer.getClass ().getInterfaces (),invocationHandler); //通过代理对象执行方法 singerProxy.sing (); } }