1.什么设计模式?
设计模式就是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间和经验和错误总结出来的。
设计模式是一套被反复使用的、多数人知晓、经过分类编目的、代码设计经验的总结。
2.设计模式的作用是什么?
使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。
3.常见的设计模式
常见的设计模式有23种
3.1单例模式
单例模式--保证一个类仅有一个实例
当类被频繁地创建与销毁的时候,我们使用单例模式,这样可以减少内存的开销,避免对资源的多重占用
单例模式条件:
1.构造方法私有
2.提供一个静态方法【公共】返回创建好的当前类对象
两种表示方式:
懒汉式
例如:
package com.wangxing.test1;
/*
* 懒汉式类
*/
public class SingleObject1 {
private static SingleObject1 sobj=null;
private SingleObject1(){}
public static SingleObject1 getSingleObject1(){
if(sobj==null){
sobj=new SingleObject1();
}
return sobj;
}
}
package com.wangxing.test1;
/*
* 测试类
*/
public class TestMain {
public static void main(String[] args) {
SingleObject1 sj1=SingleObject1.getSingleObject1();
SingleObject1 sj2=SingleObject1.getSingleObject1();
System.out.println(sj1.hashCode());
System.out.println(sj2.hashCode());
if(sj1==sj2){
System.out.println("是同一个");
}
}
}
饿汉式:
例如:
package com.wangxing.test1;
/*
* 饿汉式类
*/
public class SingleObject2 {
private SingleObject2(){}
private static SingleObject2 sobj=new SingleObject2();
public static SingleObject2 getSingleObject2(){
return sobj;
}
}
package com.wangxing.test1;
/*
* 测试类
*/
public class TestMain {
public static void main(String[] args) {
SingleObject2 sj1=SingleObject2.getSingleObject2();
SingleObject2 sj2=SingleObject2.getSingleObject2();
System.out.println(sj1.hashCode());
System.out.println(sj2.hashCode());
if(sj1==sj2){
System.out.println("是同一个");
}
}
}
懒汉式与饿汉式的区别:
1.相同点:
保证当前类的对象只有一个
书写上:
1.构造方法私有
2.提供一个静态方法【公共】返回创建好的当前类对象
2.不同点
1.书写上:
懒汉式中保存当前类的对象初始为null,
饿汉式中保存当前类对象变量初始值为new好的当前类对象
2.运行速度上:
懒汉式比饿汉式稍微差一点
3.资源利用率上:
懒汉式比饿汉式稍微好一点
3.2.工厂模式
工厂模式--有一个专门的java类充当生产对象的工厂
使用工厂模式的条件:
1.需求量大
2.牵一发,动全身
工厂模式中的角色:
工厂角色---生产对象
抽象产品角色---【抽象类/接口】
具体产品---【抽象类/接口子类】
例如:
有农场生产各种水果,有西瓜,有苹果,有香蕉......
工厂角色---农场
抽象产品角色---水果
西瓜,苹果,香蕉----具体产品
例如:
package com.wangxing.test2;
/*
* 农场
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.HashMap;
public class MyFarm {
public static MyFruits createMyFruits(String name){
MyFruits fruits=null;
HashMap<String,String>menuMap=readMenu();
String className=menuMap.get(name);
//利用反射机制创建对象
try {
Class classobj=Class.forName(className);
fruits=(MyFruits)classobj.newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return fruits;
}
//读取菜单中的信息
private static HashMap<String, String> readMenu(){
HashMap<String, String> menuMap=new HashMap<String, String>();
try {
//创建读取数据的BufferedReader流
BufferedReader buff = new BufferedReader(new FileReader(new File("menu.txt")));
//保存读取出来的每一项数据
String menuitem=null;
//循环遍历文件中的数据并保存在 menuitem中
while((menuitem=buff.readLine())!=null){
//拆分数据
String menuarry[]=menuitem.split("=");
menuMap.put(menuarry[0], menuarry[1]);
}
buff.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return menuMap;
}
}
package com.wangxing.test2;
/*
* 水果
*/
public interface MyFruits {
void eat();
}
package com.wangxing.test2;
/*
* 苹果
*/
public class Apple implements MyFruits{
@Override
public void eat() {
System.out.println("我是苹果,清洗后再吃");
}
}
package com.wangxing.test2;
/*
* 香蕉
*/
public class Banana implements MyFruits{
@Override
public void eat() {
System.out.println("我是香蕉,剥皮后再吃");
}
}
package com.wangxing.test2;
/*
* 橘子
*/
public class Orange implements MyFruits{
@Override
public void eat() {
System.out.println("我是橘子,剥皮后再吃");
}
}
package com.wangxing.test2;
/*
* 测试类
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class TestMain {
public static void main(String[] args) throws Exception {
BufferedReader buff=new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入您需要的水果");
String name=buff.readLine();
MyFruits fruits=MyFarm.createMyFruits(name);
fruits.eat();
}
}
3.3.代理模式
代理模式--为其他对象提供一种代理以控制对这个对象的访问。
买火车票不一定在火车站也有可能在代售点
代理模式被分为静态代理和动态代理
3.3.1 静态代理
静态代理被分为兄弟模式和父子模式
缺点:需要额外提供业务功能实现相似的子类【工作量大】
兄弟模式:
例如:
package com.wangxing.test3;
/*
* 售票
*/
public interface SellTicket {
void maipiao();
}
package com.wangxing.test3;
/*
* 火车站
*/
public class RailwayStation implements SellTicket{
@Override
public void maipiao() {
System.out.println("火车站卖票");
}
}
package com.wangxing.test3;
/*
* 代售点
*/
public class Agent implements SellTicket{
@Override
public void maipiao() {
System.out.println("代售点卖票");
}
}
package com.wangxing.test3;
public class TestMain {
public static void main(String[] args) {
RailwayStation rs=new RailwayStation();
rs.maipiao();
Agent ag=new Agent();
ag.maipiao();
}
}
父子模式---继承关系
例如:
package com.wangxing.test4;
/*
* 火车站
*/
public class RailwayStation{
public void maipiao() {
System.out.println("火车站卖票");
}
}
package com.wangxing.test4;
/*
* 代售点
*/
public class Agent extends RailwayStation{
public void maipiao() {
System.out.println("代售点卖票");
}
}
package com.wangxing.test4;
public class TestMain {
public static void main(String[] args) {
RailwayStation rs=new RailwayStation();
rs.maipiao();
Agent ag=new Agent();
ag.maipiao();
}
}
动态代理--有一个Java类俩负责创建代理类的对象
JDK动态代理---通过java.lang.reflect包 Class Proxy类来创建代理类对象【只能为实现过某个接口的java类提供代理类对象】
例如:
package com.wangxing.test5;
/*
* 售票
*/
public interface SellTicket {
void maipiao();
}
package com.wangxing.test5;
/*
* 火车站
*/
public class RailwayStation implements SellTicket{
@Override
public void maipiao() {
System.out.println("火车站卖票");
}
}
package com.wangxing.test5;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyObject implements InvocationHandler{
//定义目标对象
private Object targetObject;
public ProxyObject(Object targetObject){
this.targetObject=targetObject;
}
//得到代理对象
public Object getProxy(){
//java.lang.reflect包 Class Proxy类
//ClassLoader loader--类加载器
ClassLoader loader=this.getClass().getClassLoader();
//Class<?>[] interfaces---接口的反射对象
Class interfaces[]=this.targetObject.getClass().getInterfaces();
//InvocationHandler h---this
return Proxy.newProxyInstance(loader, interfaces, this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
return method.invoke(targetObject, args);
}
}
package com.wangxing.test5;
public class TestMain {
public static void main(String[] args) {
RailwayStation rs=new RailwayStation();
ProxyObject pobj=new ProxyObject(rs);
SellTicket st=(SellTicket)pobj.getProxy();
st.maipiao();
}
}
CGlib代理-------CGlib是一个第三发的开发包,用的时候需要自己事先下载导入到项目中【所有的java类提供代理类对象】
例如:
package com.wangxing.test6;
/*
* 火车站
*/
public class RailwayStation{
public void maipiao() {
System.out.println("火车站卖票");
}
}
package com.wangxing.test6;
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 ProxyObject implements MethodInterceptor{
//定义目标对象
private Object targetObject;
public ProxyObject(Object targetObject){
this.targetObject=targetObject;
}
//得到代理对象
public Object getProxy(){
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(targetObject.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object proxy, Method arg1, Object[] params, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(proxy, params);
}
}
package com.wangxing.test6;
public class TestMain {
public static void main(String[] args) {
RailwayStation rs=new RailwayStation();
ProxyObject pobj=new ProxyObject(rs);
RailwayStation rst=(RailwayStation)pobj.getProxy();
rst.maipiao();
}
}
4.三者之间比较:
1.静态代理是通过在代码中显式定义一个业务实现一个代理类,在代理类中对同名的业务方法进行包装,用户通过代理类调用被包装过的业务方法;手动创建一个与目标类相同接口的子类,包装目标类
2.JDK动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现列的同名方法;【兄弟模式】
通过jdk提供的反射包中Proxy这个类,动态创建一个与目标类实现相同接口的子类对象,包装目标
3.CGlib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理【父子模式】
通过CGlib提供的Enhancer这个类,动态的创建一个目标类的子类对象,包装目标类。
静态代理 | JDK动态代理 | CGlib动态代理 |
手动创建代理类 | 动态生成代理类对象 | 动态生成代理类镀锡 |
jdk提供的反射包中Proxy这个类 | CGlib提供的Enhancer这个类 | |
代理对象 | 只能为实现过接口的java类创建代理对象 | 为任何类创建代理对象 |