认识设计模式
介绍:
设计模式是人们在长期的软件开发中的经验总结,是对某些特定问题的经过实践检验的特定解决方法,是软件设计中的“三十六计”.
作用:
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);
}
}
小结

设计模式是面向对象程序设计在实际应用中的集中体现。设计模式可以提高软件复用性,使开发出来的软件更易于扩展,更容易适应需求变化。
本文介绍了设计模式在Java开发中的重要性,包括其作为经验总结的作用,促进系统复用和团队沟通的功能。讨论了面向对象设计原则,通过简单工厂模式和依赖倒置原则的示例来阐述其应用。接着探讨了代理模式,包括静态代理、JDK动态代理和CGLIB动态代理的实现细节,展示了如何在实际场景中运用这些代理模式。
9171

被折叠的 条评论
为什么被折叠?



