主要总结了一些类或对象组合在一起的经典结构
在不改变原始类(或叫被代理类)代码的情况下,通过引入代理类来给原始类附加功能,对客户端不透明
应用场景:
业务系统的非功能性需求开发:如打印日志,记录耗时,事务控制,幂等,限流,鉴权等等 rpc框架(远程请求包装成代理),缓存
实现:
代理类和被代理类实现同一个接口,代理类组合一个被代理类对象 代理类继承被代理类
分类:
静态代理:指手动编码每个被代理类的代理类 动态代理:利用jdk动态代理(实现同一接口)或 cglib(继承)实现的动态生成代理类
/**
* 继承实现的代理模式
*/
public class UserServiceProxy extends UserService {
@Override
public void action() {
//附加功能
System.out.println("代理类-action方法 执行了。。。");
super.action();
}
}
public class UserService {
public void action() {
System.out.println("被代理类-action方法 执行了。。。");
}
}
public interface UserService {
void action();
}
public class UserServiceImpl implements UserService {
@Override
public void action() {
System.out.println("被代理类-action方法 执行了。。。");
}
}
/**
* 基于接口实现的代理模式
*/
public class UserServiceProxy implements UserService {
private final UserServiceImpl userService = new UserServiceImpl();
@Override
public void action() {
//附加功能
System.out.println("代理类-action方法 执行了。。。");
userService.action();
}
}
/**
* 动态代理模式:基于接口实现-jdk动态代理
* 基于继承实现,cglib字节码技术可以动态代理
*/
public class UserServiceProxy {
private final UserServiceImpl userService = new UserServiceImpl();
public void action() {
UserService proxyService = (UserService) Proxy.newProxyInstance(
UserServiceProxy.class.getClassLoader(),
userService.getClass().getInterfaces(),
(proxy, method, args) -> {
//附加功能
Object obj = method.invoke(userService, args);
return obj;
});
proxyService.action();
System.out.println("代理类-action方法 执行了。。。");
}
}
不常用,将抽象部分与它的实现部分分离,使它们都可以独立地变化 一个类存在两个(或多个)独立变化的维度,我们通过组合的方式,让这两个(或多个)维度可以独立进行扩展
public abstract class Shape {
protected Color color;
public Shape(Color color) {
this.color = color;
}
public abstract void printShape();
}
public class CircleShape extends Shape {
public CircleShape(Color color) {
super(color);
}
@Override
public void printShape() {
color.printColor();
System.out.println("圆形");
}
}
public class SquareShape extends Shape {
public SquareShape(Color color) {
super(color);
}
@Override
public void printShape() {
color.printColor();
System.out.println("正方形");
}
}
public interface Color {
void printColor();
}
public class RedColor implements Color {
@Override
public void printColor() {
System.out.println("红色");
}
}
public class WhiteColor implements Color {
@Override
public void printColor() {
System.out.println("白色");
}
}
以对客户端透明的方式,动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活
应用例子:
购买煎饼,客户可自由选择加鸡蛋,加肉松,加火腿等等 java-io类中的经典实现
/**
* 抽象的装饰器
*/
public abstract class Decorator implements Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
/**
* 具体的装饰器1
*/
public class ConcreteDecorator1 extends Decorator {
public ConcreteDecorator1(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
addedOperation();
}
private void addedOperation() {
System.out.println("增加装饰器1");
}
}
/**
* 具体的装饰器2
*/
public class ConcreteDecorator2 extends Decorator {
public ConcreteDecorator2(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
addedOperation();
}
private void addedOperation() {
System.out.println("增加装饰器2");
}
}
/**
* 抽象构件
*/
public interface Component {
void operation();
}
/**
* 具体的构件1
*/
public class ConcreteComponent1 implements Component {
@Override
public void operation() {
System.out.println("具体的构件1");
}
}
/**
* 具体的构件2
*/
public class ConcreteComponent2 implements Component {
@Override
public void operation() {
System.out.println("具体的构件2");
}
}
public class DecoratorClient {
public static void main(String[] args) {
//java-io类库有同样的装饰器实现
Component component1 = new ConcreteComponent1();
ConcreteDecorator1 concreteDecorator1_1 = new ConcreteDecorator1(component1);
ConcreteDecorator2 concreteDecorator1_2 = new ConcreteDecorator2(concreteDecorator1_1);
concreteDecorator1_2.operation();
System.out.println();
Component component2 = new ConcreteComponent2();
ConcreteDecorator1 concreteDecorator2_1 = new ConcreteDecorator1(component2);
ConcreteDecorator2 concreteDecorator2_2 = new ConcreteDecorator2(concreteDecorator2_1);
concreteDecorator2_2.operation();
}
}
这个模式就是用来做适配的,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作
实现方式:
类适配器(继承) 对象适配器(组合)
应用场景:
适配接口,接口兼容,java-log的经典应用(slf4j)
public interface ITarget {
void operationA();
void operationB();
}
/**
* 适配者1
*/
public class Adaptee1 {
public void operation1A() {
System.out.println("适配者1-操作A");
}
public void operation1B() {
System.out.println("适配者1-操作B");
}
}
/**
* 适配者2
*/
public class Adaptee2 {
public void operation2A() {
System.out.println("适配者2-操作A");
}
public void operation2B() {
System.out.println("适配者2-操作B");
}
}
/**
* 类适配器:缺陷,只能适配一个适配者
*/
public class ClazzAdaptor extends Adaptee1 implements ITarget {
@Override
public void operationA() {
//不需要修改,直接返回
super.operation1A();
}
@Override
public void operationB() {
//需要修改,重新实现
super.operation1B();
}
}
/**
* 对象适配器:可以综合适配多个适配者
*/
public class ObjectAdaptor implements ITarget {
private Adaptee1 adaptee1;
private Adaptee2 adaptee2;
public ObjectAdaptor(Adaptee1 adaptee1, Adaptee2 adaptee2) {
this.adaptee1 = adaptee1;
this.adaptee2 = adaptee2;
}
@Override
public void operationA() {
//不需要修改,直接返回
adaptee1.operation1A();
//adaptee2.operation2A();
}
@Override
public void operationB() {
//需要修改,重新实现
adaptee1.operation1B();
adaptee2.operation2B();
}
}
public class AdapterClient {
public static void main(String[] args) {
ITarget target1 = new ClazzAdaptor();
target1.operationA();
target1.operationB();
ITarget target2 = new ObjectAdaptor(new Adaptee1(), new Adaptee2());
target2.operationA();
target2.operationB();
}
}
门面模式为子系统提供一组统一的接口,定义一组高层接口让子系统更易用 简而言之,就是聚合一些细粒度的接口或方法组装成一个面向用户用例的接口,提高易用性,解决一致性,以及一些性能问题
不常用,将一组对象组织(Compose)成树形结构,以表示一种部分 - 整体的层次结构 应用场景,主要用于树形结构的数据