1.什么是设计模式?
设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的实验和错误总结出来的。
设计模式是一套被反复使用的,多数人知晓的,经过分类编目的,代码设计经验的总结
2.设计模式的作用是什么?
使用设计模式就是为了重用代码,让代码更容易被他人理解,保证代码可靠性。
3.常见的设计模式
常见的设计模式又23种。
3.1单例模式
单例模式---保证一个类仅有一个实例
当类被频繁地创建与销毁的时候,我们使用单例模式,这样可以减少了内存的开销,避免对资源的多重占用
单例模式条件:
1.构造方法私有
2.提供一个静态方法【公共】返回创建号的当前类对象
两种表示方式
懒汉式
例如:
package com.test1;
/**
* 懒汉式
* @author zxc
*
*/
public class SingleObject1 {
private static SingleObject1 sobj=null;
private SingleObject1(){}
public static SingleObject1 getSinleObject1(){
if(sobj==null){
sobj=new SingleObject1();
}
return sobj;
}
}
package com.test1;
public class TestMain {
public static void main(String[] args) {
SingleObject1 s1=SingleObject1.getSinleObject1();
SingleObject1 s2=SingleObject1.getSinleObject1();
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
if(s1==s2){
System.out.println("是同一对象");
}
}
}
饿汉式
例如:
package com.test1;
/**
* 饿汉式
* @author zxc
*
*/
public class SingleObject2 {
private static SingleObject2 sobj=new SingleObject2();
private SingleObject2(){}
//当在多线程情况下使用是为了保证当前类对象只有一个我们就需要添加synchornized
public static synchronized SingleObject2 getSinleObject1(){
return sobj;
}
}
package com.test1;
public class TestMain {
public static void main(String[] args) {
SingleObject2 s1=SingleObject2.getSinleObject1();
SingleObject2 s2=SingleObject2.getSinleObject1();
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
if(s1==s2){
System.out.println("是同一对象");
}
}
}
懒汉式与饿汉式的区别
相同点:保证当前类的对象只有一个
书写上:1.构造方法私有
2. 提供一个静态方法【公共】返回创建好的当前类对象
不同点:
书写上:懒汉式中保存当前类的对象变量初始为null
饿汉式中保存当前类的对象初始变量为new好的当前类对象
运行速度上:懒汉式比饿汉式稍微差一些
资源利用率:饿汉式比懒汉式稍微差一些
3.2工厂模式
工厂模式---有一个专门的java类充当当前生产对象的工厂
使用工厂模式的条件:1.需求量大 2.牵一发,动全身。
工厂模式中的角色:工厂角色---生产对象 抽象产品角色---【抽象类/接口】 具体产品-----【抽象类/接口子类】
例如:有农场生产各种水果,有西瓜,有苹果,有香蕉
工厂角色---农场
抽象产品角色---水果
西瓜、苹果、香蕉---具体产品
在项目目录下创建出一个菜单文件
苹果=com.test2.PingGuo
西瓜=com.test2.XiGua
package com.test2;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.HashMap;
public class NongChang {
public static ShuiGuo maishuiguo(String name){
ShuiGuo sg=null;
//读取菜单
HashMap<String, String> menuMap=readMenu();
//根据键得到值
String calssName=menuMap.get(name);
try{
//利用反射机制创建对象
Class classobj=Class.forName(calssName);
sg=(ShuiGuo)classobj.newInstance();
}catch(Exception e){
e.printStackTrace();
}
return sg;
}
/**
* 读取菜单
*/
private static HashMap<String, String> readMenu() {
HashMap<String, String> menuMap=new HashMap<String, String>();
try {
BufferedReader buff=new BufferedReader(new FileReader(new File("menu.txt")));
String menuitem=null;
while((menuitem=buff.readLine())!=null){
String muenuarray[]=menuitem.split("=");
menuMap.put(muenuarray[0],muenuarray[1]);
}
buff.close();
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return menuMap;
}
}
package com.test2;
public interface ShuiGuo {
void eat();
}
package com.test2;
public class PingGuo implements ShuiGuo{
@Override
public void eat() {
System.out.println("我是苹果,削皮吃");
}
}
package com.test2;
public class XiGua implements ShuiGuo{
@Override
public void eat() {
System.out.println("我是西瓜");
}
}
package com.test2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class TestMain {
public static void main(String[] args) {
BufferedReader buff=new BufferedReader(new InputStreamReader(System.in));
System.out.println("买水果");
String info;
try {
info = buff.readLine();
ShuiGuo sg=NongChang.maishuiguo(info);
sg.eat();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3.3代理模式
代理模式---为其他对象提供一种代理以控制对这个对象的访问。
买火车票不一定在火车站买,也可以去代售点
代理模式被分为兄弟模式和父子模式
缺点:需要额外提供业务功能实现相似的子类。【 工作量大】
兄弟模式---同一个接口的两个子类
例如:
package com.test3;
public interface SellPiao {
void maipiao();
}
package com.test3;
public class HuoCheZhan implements SellPiao{
@Override
public void maipiao() {
System.out.println("火车站买票");
}
}
package com.test3;
public class DaiShouDian implements SellPiao{
@Override
public void maipiao() {
System.out.println("代售点买票");
}
}
package com.test3;
public class TestMain {
public static void main(String[] args) {
HuoCheZhan hcz=new HuoCheZhan();
hcz.maipiao();
DaiShouDian dsd=new DaiShouDian();
dsd.maipiao();
}
}
父子模式---继承关系
例如:
package com.test4;
public class HuoCheZhan {
public void maipao(){
System.out.println("火车站买票");
}
}
package com.test4;
public class DaiShouDian extends HuoCheZhan{
public void maipao(){
System.out.println("代售点买票");
}
}
package com.test4;
public class TestMain {
public static void main(String[] args) {
HuoCheZhan hcz=new HuoCheZhan();
hcz.maipao();
DaiShouDian dsd=new DaiShouDian();
dsd.maipao();
}
}
动态代理---由一个java类来负责创建代理类对象
JDK动态代理---通过java.lang.reflect包Class Proxy类来创建代理类对象
例如:
package com.test5;
public interface SellPiao {
void maipiao();
}
package com.test5;
public class HuoCheZhan implements SellPiao{
@Override
public void maipiao() {
System.out.println("火车站买票");
}
}
package com.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();
//InbocationHander 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.test5;
public class TestMain {
public static void main(String[] args) {
HuoCheZhan hcz=new HuoCheZhan();
ProxyObject proxyobj=new ProxyObject(hcz);
//代理类对象
SellPiao dsd=(SellPiao)proxyobj.getProxy();
dsd.maipiao();
}
}
【只能为实现过某个接口的java类提供代理类对象】
CGlib代理---CGlib是一个第三发的开发包,用的时候需要自己实现下载导入到项目中
例如:
package com.test6;
public class HuoCheZhan {
public void maipiao(){
System.out.println("火车站买票");
}
}
package com.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 getPrxoy(){
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 {
// TODO Auto-generated method stub
return methodProxy.invokeSuper(proxy, params);
}
}
package com.test6;
public class TestMain {
public static void main(String[] args) {
HuoCheZhan hcz=new HuoCheZhan();
ProxyObject proxy=new ProxyObject(hcz);
HuoCheZhan dsd=(HuoCheZhan)proxy.getPrxoy();
dsd.maipiao();
}
}
【所有的java类提供代理类对象】
比较:
1.静态代理是通过在代码中显式定义一个业务实现类一个代理,在代理类中对同名的业务方法进行包装,用户通过代理类调用被包装过的业务方法;
手动创建一个与目标类相同的接口的子类,包装目标类。
2.JDK动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法;【兄弟模式】
通过jdk提供的反射保重Proxy这个类,动态的创建一个与目标类实现相同接口的子类对象,包装目标。
3.CGlib提供的Enhancer这个类,动态的创建一个目标类的子类对象,包装目标类。
静态代理 | JDK动态代理 | CGlib动态代理 |
手动创建代理类 | 动态生成代理类 | 动态生成代理类 |
Jdk提供的反射包中Proxy这个类 | CGlib提供的Enhancer这个类 | |
只能为实现过接口的Java类创建代理对象 | 为任何Java类创建代理对象 |