总的来说设计模式分为三大类
创建型模式(五种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。
结构型模式(七种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。
行为型模式(十一种):策略模式,模板方法模式,观察者模式,迭代子模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,中介者模式,解释器模式。
这篇我们主要讲一下结构型模式。
由于我是java开发者,我会根据设计模式在java中的应用来说说
将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作。
就是安卓充电头(Adaptee原角色)转换成type-c充电头(Target目标角色)要使用转接头(Adapter适配器角色)一样
该角色定义把其他类转换为何种接口,也就是我们的期望接口。
你想把谁转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象。
适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单:通过继承或是类关联的方式把源角色转换为目标角色。
浏览器发送请求到 控制器(DispatcherServlet)
控制器 根据请求地址, 到 HandlerMapping(处理器映射) 寻找对应的 Handler(处理器)
HanldlerMapping 返回 找到的Handler
DispatcherServlet 根据找到的Handler 找对应的HandlerAdaptor
执行对应的Handler方法
Handler 将执行结果 和 要响应的视图名 封装成 ModelAndView 对象
控制器根据返回的 ViewName 找对应的ViewResolver (视图解析ViewResolver 将 Model 渲染到 View 中
将渲染结果 返回给控制器
最终将结果响应给客户端浏览器
适配器使用就是这里的第4,5步.
是指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式。
装饰器模式的核心是功能扩展,使用装饰器模式可以透明且动态地扩展类的功能。
也就跟开闭原则一样,只做扩展,不做改变,追只不过主体编号变成了要加上的功能
基本数据类型 | 包装类 |
---|---|
int | Integer |
byte | Byte |
short | Short |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
2. MyBatis-plus中的Wrapper
使用方法
QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.isNull("name").age("age", 12).isNotNull("email"); int result = userMapper.delete(queryWrapper);
如下所示
大家应该都看过一部日本动画片《铁甲小宝》,里面的一号机器人—卡布达,在平时的时候,他是一个笨笨的但是特别可爱的机器人,当他们需要争夺和平星进行比赛的时候,他就会变身,成为战斗力爆表的卡布达,最后,他获得了他的卡布达巨人,让战斗力又提升了一个档次。这个例子中,变身卡布达以及卡布达巨人就是普通卡布达的装饰,增强卡布达的能力。
//Component(抽象构件):定义一个抽象接口以规范准备接收附加责任的对象。 public interface KaBuDa { /** * 示人的形象 */ void display(); }
//Decorator(抽象装饰类):继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。 public class Decorator implements KaBuDa { private KaBuDa kaBuDa; public Decorator(KaBuDa kaBuDa) { this.kaBuDa = kaBuDa; } @Override public void display() { this.kaBuDa.display(); } }
//ConcreteComponent(具体构件):实现抽象构件,通过装饰角色为其添加一些职责。 public class CommonKaBuDa implements KaBuDa{ @Override public void display() { System.out.println("我是普通卡布达,卡布卡布卡布"); } }
//ConcreteDecorator(具体装饰类):实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。 public class TransfigurationKaBuDa extends Decorator{ public TransfigurationKaBuDa(KaBuDa kaBuDa) { super(kaBuDa); } @Override public void display() { super.display(); System.out.println("启动超级变换形态---超级变换形态"); } }
//ConcreteDecorator(具体装饰类):实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。 public class GiantKaBuDa extends Decorator{ public GiantKaBuDa(KaBuDa kaBuDa) { super(kaBuDa); } @Override public void display() { super.display(); System.out.println("超级卡布达巨人"); } }
可以看到,这个装饰是一点一点往上加的
public class MainClass { public static void main(String[] args) { System.out.println("-----------------1--------------------"); KaBuDa commonKaBuDa = new CommonKaBuDa(); commonKaBuDa.display(); System.out.println("-----------------2--------------------"); System.out.println("蜻蜓队长: 比赛开始"); System.out.println("-----------------3--------------------"); KaBuDa transfigurationKaBuDa = new TransfigurationKaBuDa(commonKaBuDa); transfigurationKaBuDa.display(); System.out.println("-----------------4--------------------"); System.out.println("呼唤卡布达巨人"); System.out.println("-----------------5--------------------"); KaBuDa giantKaBuDa = new GiantKaBuDa(transfigurationKaBuDa); giantKaBuDa.display(); } }
-----------------1-------------------- 我是普通卡布达,卡布卡布卡布 -----------------2-------------------- 蜻蜓队长: 比赛开始 -----------------3-------------------- 我是普通卡布达,卡布卡布卡布 启动超级变换形态---超级变换形态 -----------------4-------------------- 呼唤卡布达巨人 -----------------5-------------------- 我是普通卡布达,卡布卡布卡布 启动超级变换形态---超级变换形态 超级卡布达巨人
结果看到,对卡布达不断进行进行装饰,最后达到拥有卡布达巨人的无敌状态。
一般情况下,装饰器模式没有抽象的被装饰接口,只有一个具体的被装饰对象,这是就考虑去掉Component
类(接口),把Decorator
作为一个ConcreteComponent
的子类。如下图所示:
装饰器是继承的有力补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用
通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果
装饰器完全遵守开闭原则
是为某个对象提供一个代理对象,并且由代理对象控制对原对象的访问。代理模式通俗来讲就是我们生活中常见的中介。
//出租房子 public interface Rent { void rent(); }
//房东 public class Host implements Rent { @Override public void rent() { //打印 System.out.println("房东有房子出租!"); } }
//中介 public class Proxy implements Rent { private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } @Override public void rent() { host.rent(); seeHouse(); hetong(); fare(); } public void seeHouse() { //打印 System.out.println("See House 看房子"); } public void hetong(){ //打印 System.out.println("签约租凭合同"); } public void fare(){ //打印 System.out.println("收取中介费用!"); } }
public class Client { public static void main(String[] args) { //房东出租房子给中介代理 Host host = new Host(); //代理。帮助房东出租房子,会有一些附属的操作 Proxy proxy = new Proxy(host); // proxy.rent(); } }
一个真实角色就会产生一个代理角色;代码量会翻倍开发效率会变低
public interface UserService { public void add(); public void delete(); public void update(); public void query(); }
//真实对象 public class UserServiceImpl implements UserService{ @Override public void add() { System.out.println("增加了一个用户"); } @Override public void delete() { System.out.println("删除了一个用户"); } @Override public void update() { System.out.println("修改了一个用户"); } @Override public void query() { System.out.println("查询了一个用户"); } }
public class UserServiceProxy implements UserService{ private UserServiceImpl userService; public void setUserService(UserServiceImpl userService) { this.userService = userService; } @Override public void add() { log("add"); userService.add(); } @Override public void delete() { log("delete"); userService.delete(); } @Override public void update() { log("update"); userService.update(); } @Override public void query() { log("query"); userService.query(); } //日志方法 public void log(String msg){ System.out.println("使用了"+msg+"方法"); } }
public class Client { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); UserServiceProxy proxy = new UserServiceProxy(); proxy.setUserService(userService); proxy.add(); } }
动态代理和静态代理角色一样
动态代理的代理类是动态生成的,不是我们直接写好的!
此处留白,作者还在学习
AOP的作用: 提供声明式事务,允许用户自定义切面.
AOP底层使用动态代理,有两种情况
有接口的情况,使用JDK动态代理;创建接口实现类代理对象,增强类的方法
没有接口情况,使用CGLIB动态代理;创建子类的代理对象,增强类的方法
给某层创建一个切面,并且在这个切面中放入一些方法(增强)
AOP的JDK动态代理
调用 newProxyInstance 方法,方法有三个参数:
public static Object newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h)
方法有三个参数:
第一参数,类加载器
第二参数,增强方法所在的类,这个类实现的接口,支持多个接口
第三参数,实现这个接口 InvocationHandler,创建代理对象,写增强的部分
编写JDK动态代理
public interface UserDao { public int add(int a,int b); public String update(String id); }
public class UserDaoImpl implements UserDao{ @Override public int add(int a,int b) { return a+b; } @Override public String update(String id) { return id; } }
//创建代理对象代码 public class UserDaoProxy implements InvocationHandler { //把创建的是谁的代理对象,把谁传递过来 //有参构造传递 private Object obj; public UserDaoProxy(Object obj) { this.obj = obj; } //增强的逻辑 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //方法之前 System.out.println("方法之前执行..."+method.getName()+":传递的参数..."+ Arrays.toString(args)); //被增强的方法执行 Object res = method.invoke(obj, args); //方法之后 System.out.println("方法之后执行..."+obj); return res; } }
//使用 Proxy 类创建接口代理对象 public class JDKProxy { public static void main(String[] args) { //创建接口实现类代理对象 Class[] interfaces = {UserDao.class}; UserDaoImpl userDao = new UserDaoImpl(); UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao)); int res = dao.add(1, 2); System.out.println("result:"+res); } }
回过头来我们再看看AOP的具体信息
类里面哪些方法可以被增强,这些方法称为连接点
实际被真正增强的方法,称为切入点
把通知应用到切入点过程
AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作
基于AspectJ实现AOP操作
基于xml配置文件实现
基于注解方式实现(使用)
在项目工程中引入AOP相关依赖
org.springframework spring-aspects 5.2.15.RELEASE org.aspectj aspectjweaver 1.9.9 aopalliance aopalliance 1.0 org.aspectj aspectjtools 1.9.9 cglib cglib 3.3.0
切入点表达式
切入点表达式作用
:知道对哪个类里面的哪个方法进行增强
语法结构
:
execution (【权限修饰符】【返回类型】【类全路径】【方法名称】(【参数列表】))
举例1:对com.jin.dao.UserDao类里面的add进行增强
execution(* com.jin.dao.UserDao.add(..))
execution(* com.jin.dao.UserDao.*(..))
execution(* com.jin.dao.*.*(..))
//被增强的类 public class User { public void add(){ System.out.println("add ..."); } }
创建增强类(编写增强逻辑)
//增强类 public class UserProxy { //前置通知 public void before(){ System.out.println("before ..."); } }
进行通知的配置
//被增强的类 @Component public class User { ... } //增强类 @Component public class UserProxy { ... }
//增强类 @Component @Aspect //生成代理对象 public class UserProxy { ... }
配置不同类型的通知
//增强类 @Component @Aspect //生成代理对象 public class UserProxy { //前置通知 //@Before注解表示作为前置通知 @Before(value = "execution(* com.jin.aopanno.User.add(..))") public void before(){ System.out.println("before ..."); } @AfterReturning(value = "execution(* com.jin.aopanno.User.add(..))") public void afterReturning(){ System.out.println("afterReturning ..."); } @After(value = "execution(* com.jin.aopanno.User.add(..))") public void after(){ System.out.println("after ..."); } @AfterThrowing(value = "execution(* com.jin.aopanno.User.add(..))") public void afterThrowing(){ System.out.println("AfterThrowing ..."); } @Around(value = "execution(* com.jin.aopanno.User.add(..))") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕之前 ..."); proceedingJoinPoint.proceed(); System.out.println("环绕之后 ..."); } }
相同的切入点抽取
//增强类 @Component @Aspect //生成代理对象 public class UserProxy { //相同切入点抽取 @Pointcut(value = "execution(* com.jin.aopanno.User.add(..))") public void pointdemo(){} //前置通知 //@Before注解表示作为前置通知 @Before(value = "pointdemo()") public void before(){ System.out.println("before ..."); } }
有多个增强类多同一个方法进行增强,设置增强类优先级
@Component @Aspect //生成代理对象 @Order(1) //优先级(数字值越小优先级越高) public class PersonProxy { ... }
完全使用注解开发
@ComponentScan(basePackages = {"com.jin.pojo"}) @Configuration @EnableAspectJAutoProxy(proxyTargetClass = true) //默认EnableAspectJAutoProxy为false public class SpringConfig { }
@Test public void MyTest01(){ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); User user = context.getBean("user", User.class); user.add(); }
//被增强类 public class Book { public void buy(){ System.out.println("buy ...."); } } //增强类 public class BookProxy { public void before(){ System.out.println("before ..."); } }
@Test public void MyTest(){ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); Book book = context.getBean("book", Book.class); book.buy(); } }
上一篇:zukz2刷机原生安卓
下一篇:荣耀7刷机包安卓原生