java基础之设计模式

设计模式

1. 设计模式是什么?设计模式的作用?
答:设计模式是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
设计模式的作用:为了代码的可重用性、让代码更容易被他人理解、保证代码的可靠性

2. 单例模式的两种表示方式以及区别?
答:懒汉模式:在静态方法中初始化。时间换空间(不推荐,时间很重要)。
懒汉式的单例模式有线程安全问题,当多线程访问的时候,会出现多个实例。
饿汉模式:在声明对象就初始化。空间换时间(推荐,空间不是问题)。
运行速度:饿汉模式比懒汉模式快。
空间利用率:懒汉模式比饿汉模式更节省空间。

3. 简单工厂模式的角色,编写简单工厂模式?
答:简单工厂模式一般定义:简单工厂又叫静态工厂,由一个工厂对象决定创建哪一个产品对象。
角色分为:抽象产品角色、工厂角色、具体产品角色。
实例:有一个农场负责生产各种水果,有苹果,有草莓,有葡萄。

package com.click369.test;
/**
 * 水果接口--抽象产品角色
 * @author Administrator
 *
 */
public interface ShuiGuo {
	public  void  eat();
}
package com.click369.test;
/**
 * 葡萄类--具体产品角
 * 抽象产品角色有继承/实现关系
 * @author Administrator
 *
 */
public class PuTao implements ShuiGuo{
	@Override
	public void eat() {
		System.out.println("我吃的是葡萄");
	}
}
package com.click369.test;
/**
 * 草莓类--具体产品角
 * 抽象产品角色有继承/实现关系
 * @author Administrator
 *
 */
public class CaoMei implements ShuiGuo{
	@Override
	public void eat() {
		System.out.println("我吃的是草莓");
	}
}
package com.click369.test;
/**
 * 苹果类--具体产品角
 * 抽象产品角色有继承/实现关系
 * @author Administrator
 *
 */
public class PingGuo implements ShuiGuo{
	@Override
	public void eat() {
		System.out.println("我吃的是苹果");
	}
}
package com.click369.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.HashMap;
/**
 * 农场类--工厂角色
 * 生产各种水果【苹果,草莓,葡萄】
 * @author Administrator
 *
 */
public class NongChang {
	/**
	 * 读取菜单
	 * @return
	 */
	public  static HashMap<String,String>  getmenu(){
		HashMap<String,String> menu=new HashMap<String,String>();
		try {
		File file=new File("menu.txt");
		if(!file.exists()){
				file.createNewFile();
		}
		BufferedReader readmenu=new BufferedReader(new FileReader(file));
		String temp=null;
		while((temp=readmenu.readLine())!=null){
			String info[]=temp.split("=");
			menu.put(info[0],info[1]);
		}
		readmenu.close();
		}catch (Exception e) {
			e.printStackTrace();
		}
		return menu;
	}
	/**
	 * 根据客户需求选择生产对应的水果
	 * @param shuiguoname
	 * @return
	 */
	public static  ShuiGuo  getShuiGuo(String shuiguoname){
		ShuiGuo shuiguo=null;
		try{
		String classname=getmenu().get(shuiguoname);
			if(classname==null || classname.equals("")){
				shuiguo=null;
			}
			Class classobj=Class.forName(classname);
			shuiguo=(ShuiGuo)classobj.newInstance();
		}catch(Exception e){
			e.printStackTrace();
		}
		return shuiguo;
	}
}

Menu.txt
苹果=com.click369.test2.PingGuo
草莓=com.click369.test2.CaoMei
葡萄=com.click369.test2.PuTao

4. 代理模式的分类?比较?
答:代理模式分为:静态代理和动态代理
静态代理:让代理类继承目标类(父子模式)。

package com.click369.test;
/**
 * 目标类--主要提供对学生信息的添加,删除,修改,查询
 * 
 * @author Administrator
 *
 */
public class StudentService {
	public void addStudentInfo(){
		System.out.println("完成添加学生信息的动作");
	}
	public void updateStudentInfo(){
		System.out.println("完成修改学生信息的动作");
	}
	public void deleteStudentInfo(){
		System.out.println("完成删除学生信息的动作");
	}
	public void selectStudentInfo(){
		System.out.println("完成查询学生信息的动作");
	}
}
package com.click369.test;
/**
 * 代理类
 * 基础目标类
 * @author Administrator
 *
 */
public class StudentServiceProxy extends StudentService{
	public  void savelog(){
		System.out.println("记录日志");
	}
	@Override
	public void addStudentInfo() {
		super.addStudentInfo();
		savelog();
	}
	@Override
	public void updateStudentInfo() {
		super.updateStudentInfo();
		savelog();
	}
	@Override
	public void deleteStudentInfo() {
		super.deleteStudentInfo();
		savelog();
	}
	@Override
	public void selectStudentInfo() {
		super.selectStudentInfo();
		savelog();
	}
}

让代理类实现与目标类相同的接口(兄弟模式)。

package com.click369.test;
public interface Service {
	public void addStudentInfo();
	public void updateStudentInfo();
	public void deleteStudentInfo();
	public void selectStudentInfo();
}
package com.click369.test;
/**
 * 目标类--主要提供对学生信息的添加,删除,修改,查询
 * 
 * @author Administrator
 *
 */
public class StudentService implements Service{
	public void addStudentInfo(){
		System.out.println("完成添加学生信息的动作");
	}
	public void updateStudentInfo(){
		System.out.println("完成修改学生信息的动作");
	}
	public void deleteStudentInfo(){
		System.out.println("完成删除学生信息的动作");
	}
	public void selectStudentInfo(){
		System.out.println("完成查询学生信息的动作");
	}
}
package com.click369.test;
/**
 * 代理类
 * 基础目标类
 * @author Administrator
 *
 */
public class StudentServiceProxy implements Service{
	public  void savelog(){
		System.out.println("记录日志");
	}
	@Override
	public void addStudentInfo() {
		System.out.println("完成添加学生信息的动作");
		savelog();
	}
	@Override
	public void updateStudentInfo() {
		System.out.println("完成修改学生信息的动作");
		savelog();
	}
	@Override
	public void deleteStudentInfo() {
		System.out.println("完成删除学生信息的动作");
		savelog();
	}
	@Override
	public void selectStudentInfo() {
		System.out.println("完成查询学生信息的动作");
		savelog();
	}
}

静态代理的缺点:需要为每一个目标类单独创建一个代理类。
代理类中代码大部分是重复目标类中代码。
动态代理分为:JDK动态代理和Cglib动态代理。
动态代理的代理类是在动态生成的。也就是JVM通过反射获取代码生成代理类。
JDK动态代理只能处理有接口实现关系的java类。

package com.click369.test;
public interface Service {
	public void addStudentInfo();
	public void updateStudentInfo();
	public void deleteStudentInfo();
	public void selectStudentInfo();
}
package com.click369.test;
/**
 * 目标类--主要提供对学生信息的添加,删除,修改,查询
 * 
 * @author Administrator
 *
 */
public class StudentService implements Service{
	public void addStudentInfo(){
		System.out.println("完成添加学生信息的动作");
	}
	public void updateStudentInfo(){
		System.out.println("完成修改学生信息的动作");
	}
	public void deleteStudentInfo(){
		System.out.println("完成删除学生信息的动作");
	}
	public void selectStudentInfo(){
		System.out.println("完成查询学生信息的动作");
	}
}
package com.click369.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * 专门用来生成目标类的代理类对象的java类
 * 1.实现InvocationHandler接口
 * 2.重写InvocationHandler接口提供的invoke
 * @author Administrator
 *
 */
public class MyCreateProxyObjectClass implements InvocationHandler{
	//定义一个目标类对象
	private Object  targetObject;
	public MyCreateProxyObjectClass(Object  targetObject){
		this.targetObject=targetObject;
	}
	//得到一个代理类的对象
	 public Object  getProxyObject(){
		 //第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
		 //第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了
		 //第三个参数handler, 我	们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
		 return Proxy.newProxyInstance(this.getClass().getClassLoader(), 
				 targetObject.getClass().getInterfaces(), this);
	 }
	 private void savelog(){
		 System.out.println("记录日志");
	 }
	/**
	 *  proxy:指代我们所代理的那个真实对象
	    method:指代的是我们所要调用真实对象的某个方法的Method对象
        args:指代的是调用真实对象某个方法时接受的参数
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object obj=method.invoke(targetObject, args);
		savelog();
		return obj;
	}
}
package com.click369.test;
public class TestMain {
	public static void main(String[] args) {
		//Service service=new StudentService();
		//service.addStudentInfo();
		StudentService service=new StudentService();
		//创建代理类对象的java类对象
		//需要一个目标类对象
		MyCreateProxyObjectClass mcpc=new MyCreateProxyObjectClass(service);
		//得到目标类的代理类对象
		Service ser=(Service)mcpc.getProxyObject();
		ser.addStudentInfo();
	}
}

Cglib动态代理:

//被代理类
public class RealSubject {
    public void Request() {	
        System.out.println("执行具体的功能");
    }
     
    public final void RequestFinal() {
        System.out.println("执行具体的功能(final)");
    }
}

//生成代理对象的java类
public class ProxyInterceptor implements MethodInterceptor {
    public Object intercept(Object proxy, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib动态代理开始");
        Object result = methodProxy.invokeSuper(proxy, params);
        System.out.println("cglib动态代理开始");
        return result;
    }
     
    //创建代理类实例
    public Object newProxy(Object target)
    {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }
}

//测试类
public class Client {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
         
        ProxyInterceptor proxyInterceptor = new ProxyInterceptor();
        RealSubject subject = (RealSubject)proxyInterceptor.newProxy(realSubject);
        subject.Request();
        subject.RequestFinal();
    }
}

比较:

  1. 静态代理是通过在代码中显示定义一个业务实现类一个代理,在代理类中对同名的业务方法进行包装,用户通过代理类调用被包装过的业务方法。
    手动创建一个与目标类相同接口的子类,包装目标类。
    JDK动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法(兄弟模式)。通过JDK提供的反射包中Proxy这个类,动态的创建与一个目标类实现相同接口的子类对象包装目标。
    Cglib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理(父子模式)。
    通过Cglib提供的Enhancer这个类,动态的创建一个目标类的子类对象,包装目标类。

5. 《大话设计模式》
《大话设计模式》是2007年清华大学出版社出版的图书,作者是程杰。本书中以情景对话的形式,用多个小故事或编程示例来组织讲解GoF总结的23个设计模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值