java开发框架基础-设计模式

本文介绍了设计模式在Java开发中的重要性,包括其作为经验总结的作用,促进系统复用和团队沟通的功能。讨论了面向对象设计原则,通过简单工厂模式和依赖倒置原则的示例来阐述其应用。接着探讨了代理模式,包括静态代理、JDK动态代理和CGLIB动态代理的实现细节,展示了如何在实际场景中运用这些代理模式。

认识设计模式

介绍:
设计模式是人们在长期的软件开发中的经验总结,是对某些特定问题的经过实践检验的特定解决方法,是软件设计中的“三十六计”.
作用:
1.使开发者可以更加简单方便地复用 成功的设计和体系结构
2.帮助开发者做出有利于系统复用的选择,避免损害系统复用性的设计.
3.使其他开发者更加容易理解其设计思路,便于团队交流。

在这里插入图片描述
设计模式之间的关系
在这里插入图片描述
为什么使用设计模式
在这里插入图片描述
由此不难想象,如果程序中比较基础的模块发生变化,将导致该模块的所有调用者都要修改代码,影响了其他模块的重用。

面向对象设计原则

在这里插入图片描述
在这里插入图片描述

设计模式的应用

简单工厂模式
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
简单工厂+依赖倒置原则
在这里插入图片描述
简单工厂模式+参数
在这里插入图片描述
示例:
定义发负责创建NewsDao示例的工厂类。

//简单工厂模式
public class SimplDaoFactory {
    //创建NewsDao实例的工厂方法
    public static NewsDao getInstance(String key){
       switch (key){
           case "mysql":
               return new NewsDaoMySqlImpl();
           case "oracle":
               return new NewsDaoOracleImpl();
           case "redis":
               return new NewsDaoRedisImpl();
           default:
               throw new RuntimeException("无效的数据库类型"+key+",DAO获取失败");
       }
    }
}

根据依赖倒置原则,使用setter方法传递依赖关系。代码如下:

public class NewsDaoServiceImpl implements NewsDaoService {
   private NewsDao dao;
   public void setDao(NewsDao dao){
       this.dao=dao;
   }
    @Override
    public void addNews(News news) {
        dao.save(news);
    }
}

在测试方法中,通过NewsServiceImpl类的setter方法传递依赖关系

public class Test {
    public static void main(String[] args) {
        NewsDao dao = SimplDaoFactory.getInstance("mysql");
        NewsDaoServiceImpl service = new NewsDaoServiceImpl();
        service.setDao(dao);
    }
}

小结
在这里插入图片描述

工厂模式
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
示例:
创建工厂接口

public interface AbstractFactory {
    public NewsDao getInstance();
}

为不同的NewsDao实现创建相对应的具体工厂,以NewsDaoMysqlImol实例的工厂为例

public class MySqlDaoFactory  implements AbstractFactory {

    @Override
    public NewsDao getInstance() {
        return new NewsDaoMySqlImpl();
    }
}

在测试方法中通过特定工厂生产相关的NewsDao实例

public class Test2 {
    public static void main(String[] args) {
        AbstractFactory factory = new MySqlDaoFactory();//改变具体工厂可创建不同产品
        NewsDao dao = factory.getInstance();
        NewsDaoServiceImpl service = new NewsDaoServiceImpl();
        service.setDao(dao);

    }
}

工厂模式被广泛的应用在java框架技术中,

代理模式

在这里插入图片描述
静态代理
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
示例:实现房产中介对买家的代理效果
1.定义抽象主题:买家业务接口

package 抽象主题;
//买家接口
public interface Buyer {
    //查看房屋
    public String havealook();
}

2.定义真实主题:买家业务实现类

public class RealBuyer implements Buyer {
    private Logger logger = Logger.getLogger(RealBuyer.class);
    @Override
    public String havealook() {
        System.out.println("实地查看一下");
        return "一些意见";
    }
}

3.定义代理:对Buyer接口的 havealook() 方法流程进行完善。

public class IntermediaryImpl implements Buyer {
    Logger logger = Logger.getLogger(IntermediaryImpl.class);
    private Buyer target;//被代理的目标对象
    public IntermediaryImpl(Buyer target){
        this.target=target;
    }
    //对目标对象业务进行代理
    @Override
    public String havealook() {
        before();
        String feedback = target.havealook();//执行目标对象的实际业务
        after();
        return "看房记录:买家反馈”"+feedback+"“";

    }
    public void before(){
        System.out.println("前期准备");
        System.out.println("查找房源");
        System.out.println("和卖家沟通事件");
    }
    public void after(){
        System.out.println("后期跟踪");
        System.out.println("和买家沟通意见");
    }
}

4.对代理效果测试

public class Test {
    public static void main(String[] args) {
        Buyer buyer = new IntermediaryImpl(new RealBuyer());
        String result = buyer.havealook();
        System.out.println(result);

    }
}

代理模式优点
在这里插入图片描述
静态代理-继承
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
jdk动态代理
在这里插入图片描述
JDK动态代理核心API是java.lang.reflect包下的InvocationHandler接口和Proxy类:
在这里插入图片描述
示例:使用jdk动态代理方式实现房产中介对买家的代理效果。
1.jdk动态代理只能针对接口实现代理,目标对象必须通过抽象主题接口实现。

public class RealBuyer implements Buyer {
    @Override
    public String havealook() {
        System.out.println("实地查看一下");
        return "一些意见";
    }
}

2.通过InvocationHandler接口定义房产中介的代理规则


public class IntermediaryInvocationHandler implements InvocationHandler {
    //被代理的目标对象
    private Object target;
    public void setTarget(Object target){
        this.target=target;
    }
    //为被代理的接口方法定义的代理业务规则
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object feedback = method.invoke(target,args);//反射执行目标对象的实际业务
        after();
        return "看房记录:买家反馈”"+feedback+"“";
    }
    public void before(){
        System.out.println("前期准备");
        System.out.println("查找房源");
        System.out.println("和卖家沟通事件");
    }
    public void after(){
        System.out.println("后期跟踪");
        System.out.println("和买家沟通意见");
    }
}

3.定义代理工厂,使用proxy类基于前文定义的代理业务规则为指定接口动态生成代理对象。


public class IntermediaryJdkProxyFactory {
	//工厂方法
	//@target:需要被代理的目标对象
	//@return:返回说生成好的代理对象
    public static <T> T create(Object target){
        IntermediaryInvocationHandler handler = new IntermediaryInvocationHandler();
        handler.setTarget(target);
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),handler);
    }
}

4,编写测试代码:


public class Test {
    public static void main(String[] args) {
        Buyer buyer = IntermediaryJdkProxyFactory.create(new RealBuyer());
        String result = buyer.havealook();
        System.out.println(result);
    }
}

测试代码中,buyer对象的类型是一个动态创建的Buyer接口的实现类,调用该实现类的任何一个Buyer接口方法都会执行IntermediaryInvocationHandler 中定义的invoke()方法,invoke()方法会执行代理业务规则并调用被代理对象中相关的实际业务方法。

CGLIB动态代理
在这里插入图片描述
使用CDLIB代理需要先从https://github.com/cglib/cglib/releases下载所需的jar文件,选择cglib.nodep-3.3.0.jar,并将其引用到项目中。

使用CGLIB静态代理会用到其net.sf.cglib.proxy包中的MethodInterceptor接口和Enhancer类

在这里插入图片描述

在这里插入图片描述
步骤:
在这里插入图片描述
示例:如果RealBuyer是一个没有实现接口的类,使用CGLIB动态代理方法实现房产中介对买家的代理效果,关键代码如下:
1.通过MethedInterceptor接口定义房产中介的代理业务规则。

public class IntermediaryMethod implements MethodInterceptor {
    /**
     * 为被代理的方法定义的代理业务规则
     */
    @Override
    public Object intercept(Object proxy, Method method, Object[] ages, MethodProxy methodProxy) throws Throwable {
        before();
        //调用父类的原始方法
        Object feedback = methodProxy.invokeSuper(proxy,ages);
        after();
        return "看房记录,买家反馈"+feedback;
    }
    public void before(){
        System.out.println("前期准备");
        System.out.println("查找房源");
        System.out.println("和卖家沟通时间");
    }
    public void after(){
        System.out.println("后期跟踪");
        System.out.println("和买家沟通意见");
    }
}

2.定义代理工厂,使用Enhancer类基于前文定义的代理业务规则为指定类动态生成代理对象

    private static IntermediaryMethod callback = new IntermediaryMethod();

    /**
     * 工厂方法
     * @param target 需要被代理的类型,即代理类需要需要继承的父类型
     * @param <T>
     * @return 代理类的实例
     */
    public static <T> T create(Class<T> target){
        Enhancer enhancer = new Enhancer();
        enhancer.setCallback(callback); //为重写方法指定回调的MethodInterceptor
        enhancer.setSuperclass(target);//指定要继承的父类型,即需要被代理的类型
        return (T) enhancer.create();//动态生成子类,创建子类实例并返回
    }
}

3.编写测试代码

public class Test {
    public static void main(String[] args) {
        RealBuyer realBuyer = IntermediaryCglibProxy.create(RealBuyer.class);
        String rs = realBuyer.havealook();
        System.out.println(rs);
    }
}

小结
在这里插入图片描述
设计模式是面向对象程序设计在实际应用中的集中体现。设计模式可以提高软件复用性,使开发出来的软件更易于扩展,更容易适应需求变化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值