icql

结构型设计模式概述

主要总结了一些类或对象组合在一起的经典结构



代理模式

在不改变原始类(或叫被代理类)代码的情况下,通过引入代理类来给原始类附加功能,对客户端不透明

应用场景:

业务系统的非功能性需求开发:如打印日志,记录耗时,事务控制,幂等,限流,鉴权等等 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)成树形结构,以表示一种部分 - 整体的层次结构 应用场景,主要用于树形结构的数据



享元模式