单例模式,工厂模式,代理模式
1.什么是设计模式?
设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结.
2.设计模式的作用是什么?
使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。
3.常见的设计模式
常见的设计模式23种
1)单例模式:
保证一个类仅有一个实例。
当类被频繁地创建与销毁的时候,我们使用单例模式,这样可以减少了内存的开销,避免对资源的多重占用。
单例模式条件:
1.构造方法私有化
2.提供一个静态方法【公共】返回创建好的当前类对象。
两种表示方式
懒汉式:
//懒汉式
public class SingletonPattern_01 {
//2.定义一个全局的类变量保存创建的对象
private static SingletonPattern_01 targeobj;
//1.构造方法私有化
private SingletonPattern_01(){}
public static SingletonPattern_01 getObj(){
if (targeobj == null) {
targeobj = new SingletonPattern_01();
}
return targeobj;
}
}
饿汉式:
//饿汉式
public class SingletonPattern_02 {
//1.创建保存返回对象的静态私有类
private static SingletonPattern_02 targerObj = new SingletonPattern_02();
//2.构造函数私有化
private SingletonPattern_02(){}
//3.创建公共的静态方法
public static synchronized SingletonPattern_02 getObj(){
return targerObj;
}
}
两者的区别:
1.运行速度上 饿汉式快于饱汉式
2.内存资源上 饱汉式比饿汉式节约内存
2)工厂模式
工厂模式----有一个专门的java类充当生产对象的工厂。
使用工厂模式的条件:
1.需求量大
2.牵一发,动全身
工厂模式中的角色:
工厂角色:生产对象
抽象产品角色:【抽象类/接口】
具体产品:【抽象类/接口子类】
例如:有农场生产各种水果,有西瓜,有苹果,有香蕉......
工厂角色: 农场
抽象产品角色: 水果
具体产品 : 西瓜,苹果,香蕉
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Set;
public class FactoryNC {
private String name = "农场";
public String getName() {
return name;
}
private HashMap<String, String> menus = new HashMap<String, String>();
//构造方法获取水果菜单
public FactoryNC() {
try {
FileReader in = new FileReader("menus.txt");
BufferedReader reader = new BufferedReader(in);
String fruit = null;
while ((fruit = reader.readLine()) != null) {
String str[] = fruit.split("=");
menus.put(str[0], str[1]);
}
reader.close();
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//购买需要的水果
public Fruites getFruites(String fruiteName){
Fruites fruites = null;
//得到set中包名+类名
String fruitesClass = menus.get(fruiteName);
try {
//通过反射机制得到水果对象
Class<?> fuiteclass = Class.forName(fruitesClass);
Object classobj= fuiteclass.newInstance();
fruites = (Fruites)classobj;
} catch (Exception e) {
e.printStackTrace();
}
return fruites;
}
//查看所有的水果
public void showmenus(){
Set<String> vlue = menus.keySet();
for (String item : vlue) {
System.out.println(item);
}
}
}
3)代理模式
代理模式: 为其他对象提供一种代理以控制对这个对象的访问。
举例:买火车票不一定在火车站买,也可以去代售点。
代理模式被分为静态代理和动态代理
静态代理有被分为兄弟模式和父子模式
缺点:需要额外提供业务功能实现相似的子类。【工作量大】
兄弟模式:同一个接口的两个子类
静态代理是通过在代码中显式定义一个业务实现类一个代理,在代理类中对同名的业务方法进行包装,用户通过代理类调用被包装过的业务方法;
缺点:需要额外提供业务功能实现相似的子类。【工作量大】
静态代理:
1)兄弟代理
接口类:
封装业务
public interface BuyPero {
void maipiao();
}
需要被代理的类
public class HuocheZhan implements BuyPero{
@Override
public void maipiao() {
System.out.println("火车站买票");
}
}
代理类
public class BrotherProxy implements BuyPero{
@Override
public void maipiao() {
System.out.println("代理商买票");
}
}
2)父子模式
//代理模式父类
public class PersonSon {
public void mainpiao(){
System.out.println("火车站的买票");
}
}
//代理类
public class Son extends PersonSon{
@Override
public void mainpiao() {
System.out.println("代理正在买票");
}
}
动态代理:
由一个java类来负责创建代理类的对象。
JDK动态代理:通过java.lang.reflect包 Class Proxy类来创建代理类对象。
CGlib代理:CGlib是一个第三发的开发包,用的时候需要自己事先下载导入到项目中。
jdk动态代理例子:
需要代理的接口业务
public interface Sell {
void maipiao();
}
需要被代理的类
public class Huochezhan implements Sell{
@Override
public void maipiao() {
System.out.println("火车站在买票~~~");
}
}
代理类:
package comjdk8dongtai;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Proxyjdk implements InvocationHandler {
private Object targetObj;
//定义目标对象
public Proxyjdk(Object targetObj){
this.targetObj = targetObj;
}
//得到代理对象
public Object getProxy(){
//java.lang.reflect包Class Proxy类
//ClassLoader loader:类加载器
ClassLoader loader = this.getClass().getClassLoader();
//Class<?>[] interfaces:接口反射对象
Class<?> interfaces[] = this.targetObj.getClass().getInterfaces();
//invocationHandler h *** this
return Proxy.newProxyInstance(loader, interfaces, (InvocationHandler) this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
return method.invoke(targetObj, args);
}
}
主类:
public class TestProxy {
public static void main(String[] args) {
Huochezhan huochezhan= new Huochezhan();
Proxyjdk dl= new Proxyjdk(huochezhan);
Sell dsd=(Sell)dl.getProxy();
dsd.maipiao();
}
}
CGlib代理:
需要被代理的类:
public class HuocheZhan {
public void maipiao(){
System.out.println("火车站在买票");
}
}
代理类:
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGlibProxy implements MethodInterceptor{
private Object target;
public CGlibProxy(Object target) {
this.target = target;
}
public Object getProxy(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object proxy, Method arg1, Object[] params, MethodProxy methodProxy) throws Throwable {
// TODO Auto-generated method stub
return methodProxy.invokeSuper(proxy, params);
}
}
主类:
public class TestMain {
public static void main(String[] args) {
HuocheZhan huocheZhan = new HuocheZhan();
CGlibProxy proxy = new CGlibProxy(huocheZhan);
HuocheZhan proxyobj = (HuocheZhan) proxy.getProxy();
proxyobj.maipiao();
}
}
比较:
1.静态代理是通过在代码中显示定义一个业务实现类的一个代理,在代理中对同名的业务方法进行包装,用户通过代理类带哦用被包装的业务方法。
手动创建一个与目标类相同的接口子类,包装目标类
2.JDK动态代理是通过接口中的方法名,在动态生成的带库中代用业务实现类中调用实现的同名方法【兄弟模式】通过jdk听过的反射包中的Proxy这个类,动态的创建一个与目标类实现的相同接口的子类对象,包装目标。
3.CGlib动态代理是通过继承业务类,身材隔行的动态代理累的是业务的子类,通过重写业务方法进行代理。【父子模式】,通过CGlib提供的Enhancer和这个类,动态的创建一个目标子类对象,包装目标类。
静态代理 | JDK动态代理 | CGlib动态代理 |
手动创建代理类 | 动态生成代理类对象。 | 动态生成代理类对象。 |
jdk提供的反射包中的Proxy这个类只能为实现过接口的Java类创建代理对象。 | CGliv提供的Enhancer这个类为任何Java类创建代理对象。 |
无奈源于不够强大