设计模式之适配器模式、委派模式、访问者模式、工厂模式、桥接模式(双维度扩展)

设计模式之适配器模式、委派模式、访问者模式、工厂模式、观察者-发布订阅模式

  • 设计模式分类:
  • 适配器模式(Adapter Pattern)
    • 定义
    • 使用场景
    • 代码实现
      • 写法一:类适配器
      • 写法二:对象适配器
    • 实际应用例子
    • 代码实现(版本一)
    • 代码实现(版本二)
  • 委派模式(delegate)
    • 定义:
    • 应用场景:
    • 现实中的例子:
    • 优缺点总结:
    • 与代理模式的区别
    • 代码实现
  • 访问者模式(visitor)
    • 定义
    • 生活中的例子
    • 适用场景
    • 代码实现
      • 基础数据结构
      • 访问者
      • 测试
    • 优缺点总结
  • 工厂模式(Factory Pattern)
    • 简单工厂模式(Simple Factory)
      • 定义:
      • 使用场景:
      • 优缺点:
      • 代码实现:
    • 工厂方法模式(Factory Method pattern)
      • 定义
      • 适用场景
      • 优缺点
      • 代码示例
    • 抽象工厂(Abstract Factory)
      • 定义
      • 适用场景
      • 优缺点
      • 代码实现
  • 代码实现
  • 桥接模式(Bridge Pattern)
    • 定义
    • 适用场景
    • 优缺点
    • 代码实现
    • 实际应用
  • 观察者模式(Observer Pattern)
    • 定义
    • 适用场景
    • 传统实现
      • 发布主题以及实现
      • 观察者实现
      • 测试
    • Guava 实现
    • 实际应用
      • 1.定义一个节点信息,用于存储基本信息以及后续扩展
      • 2.定义观察者接口
      • 3.定义一个节点管理器,用于实现注册和发布方法
      • 4.应用一:实现指定的节点刷新接口
      • 5. 应用二、派件给对应的人(通过抽象类注册)

设计模式分类:

适配器模式(Adapter Pattern)

定义

将一个类的接口变成客户端期望的另一种接口

使用场景

  1. 已经存在的类,他的方法和需求不匹配,
  2. 适配器模式不是软件设计阶段考虑的类,是由于随着软件的发展,不同产品,不同厂家功能类似、而接口不同的情况的解决方案。

总结:
适配器模式的局限性在于
1.原功能与期望的功能的输入参数和返回值要相同,即使不同也要有固定的关联关系
就像适配器经典例子中的电压一样,输入都是插头,输出都是电流。

代码实现

写法一:类适配器

类适配器采用继承的方式实现,暴漏了原方法给客户端,违法了最小职责原则,使用对象适配器能解决这一问题。

//原始类(已经存在的功能)
public class Origin {
    //已经存在的方法
    public int exitsMethod(){
        return 1;
    }
}

//目标类(开发的新功能)
public interface Target {
	// 开发的新方法
    public Boolean expectMethod(String args);
}

//测试
public class Test {
    public static void main(String[] args) {
        Adapter adapter = new Adapter();
        Boolean abc = adapter.expectMethod("abc");
        int i = adapter.exitsMethod(); //两个方法都暴漏给了客户端,不合适
    }
}

// 适配器
public class Adapter extends Origin implements Target {
    @Override
    public Boolean expectMethod(String args) {
        return exitsMethod() == 1;
    }
}

类图:
设计模式之适配器模式、委派模式、访问者模式、工厂模式、桥接模式(双维度扩展)_第1张图片

写法二:对象适配器

代码:

//原始类(已经存在的功能)
public class Origin {
    //已经存在的方法
    public int exitsMethod(){
        return 1;
    }
}

//目标类(开发的新功能)
public interface Target {

	// 开发的新方法
    public Boolean expectMethod(String args);
}

// 适配器
public class Adapter implements Target {
    private Origin origin;
    public Adapter(Origin origin) {
        this.origin = origin;
    }
    
    @Override
    public Boolean expectMethod(String args) {
        return origin.exitsMethod() == 1;
    }
}

//测试
public class Test {

    public static void main(String[] args) {
        Adapter adapter = new Adapter(new Origin());
        Boolean abc = adapter.expectMethod("abc");
    }
}

类图:
设计模式之适配器模式、委派模式、访问者模式、工厂模式、桥接模式(双维度扩展)_第2张图片

实际应用例子

需求:
现有登录方式:

  1. 用户名密码登录
    需要新增如下第三方登录功能
  2. 手机号验证码登录
  3. 微信登录
    需要实现不同的厂商的同一登录功能。

代码实现(版本一)

//============= 现有功能代码===start=====

//现有的用户名密码登录
public class PasswordLoginService {
    // 注册
    public Boolean register(String userId,String password){
        return true;
    }
    //用户密码登录
    public Boolean login(String userId,String password){
        return true;
    }
}

//============= 现有功能代码===end=====

//新增第三方登录接口
public interface ThirdPartyLogin {
    /** 手机号密码登录*/
    Boolean loginByPhone(String phone,String code);

    /**微信登录*/
    Boolean loginWechat(String openId);
}

//适配器
public class PasswordForThirdPartyLoginAdapter extends PasswordLoginService implements ThirdPartyLogin{

    @Override
    public Boolean loginByPhone(String phone, String code) {
        //缺少调用运营商校验验证码是否输入正确
        return this.loginForRegister(phone,null);
    }

    @Override
    public Boolean loginWechat(String openId) {
        //缺少调用微信平台,校验openId
        return this.loginForRegister(openId,null);
    }

    private Boolean loginForRegister(String userId,String password){
        if(password == null){
            password = "第三方登录,不需要密码";
        }
        if(super.register(userId,password)){
            super.login(userId,password);
        }
        return true;
    }
}

//测试 
public class Test {

    public static void main(String[] args) {
        PasswordForThirdPartyLoginAdapter adapter = new PasswordForThirdPartyLoginAdapter();
        adapter.login("用户命密码登录","密码");
        adapter.loginByPhone("13822992932","372652");
        adapter.loginWechat("wechatopenid");
    }
}

代码实现(版本二)

版本一有一些缺陷
适配器中缺少第三方的一些校验代码逻辑,实际开发中如果将对接第三方的代码写在这个适配器中将会变得十分臃肿。


// 原有的密码登录
public class PasswordLoginService {
    // 注册
    public Boolean register(String userId,String password){
        return true;
    }
    //用户密码登录
    public Boolean login(String userId,String password){
        return true;
    }
}

public interface ThirdPartyLogin {
    /** 手机号密码登录*/
    Boolean loginByPhone(String phone,String code);
    /**微信登录*/
    Boolean loginWechat(String openId);
}

//登录适配器接口,所有的第三方登录实现改接口
public interface LoginAdapter {
    Boolean support(LoginAdapter adapter);
    Boolean login(String userId,LoginAdapter adapter);
}

//适配器(仅转接,不承接业务)
public class PasswordForThirdPartyLoginAdapter extends PasswordLoginService implements ThirdPartyLogin {
    @Override
    public Boolean loginByPhone(String phone, String code) {
        return handleLogin(phone,new PhoneLoginAdapter());
    }

    @Override
    public Boolean loginWechat(String openId) {
        return handleLogin(openId,new WechatLoginAdapter());
    }

    private Boolean handleLogin(String userId,LoginAdapter loginAdapter){
        if(loginAdapter.support(loginAdapter)){
           return loginAdapter.login(userId,loginAdapter);
        }

        return false;
    }

}

// 抽象登录适配器,作用:抽取公共的注册登录方法
public abstract class AbstractLoginAdapter extends PasswordLoginService implements LoginAdapter {

    protected Boolean loginForRegister(String userId,String password){
        if(password == null){
            password = "第三方登录,不需要密码";
        }
        if(super.register(userId,password)){
            super.login(userId,password);
        }
        return true;
    }
}

//手机登录适配器
public class PhoneLoginAdapter extends AbstractLoginAdapter {
    @Override
    public Boolean support(LoginAdapter adapter) {
        return adapter instanceof PhoneLoginAdapter;
    }

    @Override
    public Boolean login(String userId, LoginAdapter adapter) {
        return super.loginForRegister(userId,null);
    }
}

//微信登录适配器
public class WechatLoginAdapter extends AbstractLoginAdapter {
    @Override
    public Boolean support(LoginAdapter adapter) {
        return adapter instanceof WechatLoginAdapter;
    }

    @Override
    public Boolean login(String userId, LoginAdapter adapter) {
        return super.loginForRegister(userId,null);
    }
}

//测试 
public class Test {

    public static void main(String[] args) {
        PasswordForThirdPartyLoginAdapter adapter = new PasswordForThirdPartyLoginAdapter();
        adapter.login("用户命密码登录","密码");
        adapter.loginByPhone("13822992932","372652");
        adapter.loginWechat("wechatopenid");
    }
}

委派模式(delegate)

定义:

委派模式不属于GOF23种设计模式,是一种行为模式,与门面模式类似,不同的是委派模式是运行中的行为处理逻辑。
委派模式更加注重委派的逻辑,而门面模式是一开始就定义好了的委托对象。

应用场景:

  1. 委派对象本身并不知道处理业务的逻辑,只是把请求交给其他程序来处理。
  2. 实现程序解耦

现实中的例子:

例如一个领导有很多下属,领导会跟进下属熟悉的领域进行安排工作,老板本身不参加具体事务。

优缺点总结:

委派模式能够将一个大型的任务拆分,更够通过管理子任务的执行情况解耦和提升效率。

与代理模式的区别

委派模式与代理模式也有很多相似之处,区别如下:

  1. 委派模式是行为模式,代理模式是结果模式
  2. 委派模式是任务派遣,注重结果;代理模式是代码增强,注重过程。

代码实现

代码

//员工接口
public interface Employee {
    void doSomething(String task);
}
public class EmployeeA implements Employee{
    @Override
    public void doSomething(String task) {
        System.out.println("我擅长写报告...");
    }
}

public class EmployeeB implements Employee{
    @Override
    public void doSomething(String task) {
        System.out.println("我擅长公关...");
    }
}

// 领导跟进员工的特征安排任务
public class Leader implements Employee {
    @Override
    public void doSomething(String task) {
        if("接待".equals(task)){
            new EmployeeB().doSomething(task);
        } else if("汇报".equals(task)){
            new EmployeeA().doSomething(task);
        }
    }
}

// 测试,老板发话给领导安排任务,领导找到员工
public class Boos {
    public void command(String task,Leader leader){
        leader.doSomething(task);
    }
    public static void main(String[] args) {
        new Boos().command("接待",new Leader());
    }
}

类图:
设计模式之适配器模式、委派模式、访问者模式、工厂模式、桥接模式(双维度扩展)_第3张图片

访问者模式(visitor)

定义

是一种将数据结构与数据操作分离的设计模式

生活中的例子

例如软件公司有若干码农,他们有一个共同的数据结构(姓名,KPI,bug数量,开发的功能,代码行数),对于不同的领导,如直属领导关注开发的功能,代码行数,开发部门经理关注程序员的bug数,公司CEO关注码农的KPI。

结合例子解释概念:

程序员的属性就是一个稳定的数据结构,公司的不同领导就是不同的访问者,他们关注的点(操作)各不相同。

适用场景

  1. 数据结构稳定、作用与数据结构的操作经常变化的操作
  2. 需要数据结构和数据操作分离的场景

代码实现

基础数据结构

#(一 员工抽象)
public abstract class Employee {
    //员工姓名
    private String name;
    //kpi分数
    private int kpi;
    public Employee(String name, int kpi) {
        this.name = name;
        this.kpi = kpi;
    }
    # 提供一个访问者进入的接口
    public abstract void accept(Visitor visitor);
}

#(二 程序员实现)
public class Coder extends Employee {
    public Coder(String name, int kpi) {
        super(name, kpi);
    }
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    /**
     * 产生的bug数
     */
    public Integer bugNumbers(){
        return new Random().nextInt(100);
    }
}
#(三 产品经理实现)
public class Manager extends Employee{

    public Manager(String name, int kpi) {
        super(name, kpi);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    /**
     * 经理考核上线的系统数量
     * @return
     */
    public int systemCount(){
        return new Random().nextInt(10);
    }
}

访问者

# 访问者接口
public interface Visitor {
     // 访问员工
    void visit(Coder employee);

     * 访问经理
     */
    void visit(Manager employee);
}

# 访问者实现一:CTO
public class CTOVisitor implements Visitor {

    @Override
    public void visit(Coder employee) {
        System.out.println("CTO看"+employee.getName()+"的bug数"+employee.bugNumbers());
    }

    @Override
    public void visit(Manager employee) {
        System.out.println("CTO看"+employee.getName()+"的系统上线数"+employee.systemCount());
    }
}

# 访问者实现二:CEO
public class CEOVisitor implements Visitor {

    @Override
    public void visit(Coder employee) {
        System.out.println("CEO看"+employee.getName()+"的KPI"+employee.getKpi());
    }

    @Override
    public void visit(Manager employee) {
        System.out.println("CEO看"+employee.getName()+"的KPI"+employee.getKpi());
    }
}

测试

public class Test {
    private static List<Employee> employeeList = new ArrayList();
    static {
        Coder coder = new Coder("张小开", 90);
        Manager manager = new Manager("李经理", 90);
        employeeList.add(coder);
        employeeList.add(manager);
    }
    public static void main(String[] args) {
        System.out.println("CTO===看员工");
        CTOVisitor ctoVisitor = new CTOVisitor();
        for (Employee employee : employeeList) {
            employee.accept(ctoVisitor);
        }

        System.out.println("CEO=====看员工");
        CEOVisitor ceoVisitor = new CEOVisitor();
        for (Employee employee : employeeList) {
            employee.accept(ceoVisitor);
        }
    }
}

优缺点总结

优点

  1. 解耦的数据结构和数据的相关操作
  2. 随时扩展访问者对数据结构进行不同的数据操作

缺点

  1. 如果数据结构不稳定,需要经常修改或删除则访问者需要做出对于的操作,违背开闭原则。
  2. 违背了依赖倒置原则,访问者依赖具体的对象,而没有依赖抽象。(如上述例子中访问者依赖了程序员、产品经理的具体实现,如果在增加一种员工类型则访问者接口又要增加一种访问类型,所有的访问者实现都需要调整)

总结:

访问者模式是一种比较复杂的设计模式,使用场景较少,数据行为类设计模式。

工厂模式(Factory Pattern)

简单工厂模式(Simple Factory)

定义:

是指由一个工厂根据不同的参数决定参加出那种产品。

使用场景:

  1. 需要创建的对象比较少
  2. 客户端只需要传入工厂类的参数,不需要关心创建对象的逻辑。

优缺点:

优点:只需要传入一个参数就可以获取想要的对象。
缺点:工厂类的职责过重,增加新的对象时需要修改创建工厂类的判断逻辑,违被了开闭原则

代码实现:

需求

根据不同的审批流程渠道获取申请人信息

实现代码:

public class CustomerSimpleFactory {

    public static CustomerInterface getInstance(String taskType){
        if("1".equals(taskType)){
            return new MainCustomerService();
        }else if("2".equals(taskType)){
            return new EleCustomerService();
        }else if("3".equals(taskType)){
            return new PreCustomerService();
        }else if("4".equals(taskType)){
            return new QrCustomerService();
        }
        return null;
    }

    public static CustomerInterface getInstance2(Class<? extends CustomerInterface> clazz){
        try {
            return clazz.newInstance();
        } catch (Exception e) {
        }
        
        return null;
    }
}

工厂方法模式(Factory Method pattern)

定义

定义一个工厂的接口,由子类实现工厂接口来决定创建的对象,工厂方法模式让类的实例推迟到子类工厂中

适用场景

1.创建对象需要由大量的逻辑,(实例化目标类时逻辑比较复杂)
2.预计有较多的新实例需要加入

优缺点

优点:

1.客户不需要知道类具体的创建细节 ,只需要关系返回的结果(与简单工厂一样有这个优点,似乎所有的工厂都是这个优点)
2.方便扩展新产品,符合开闭原则

缺点:

1.类的代码太多,增加了类的结构复杂度,2.增加了系统的抽象复杂度。

代码示例

/**
 * 工厂方法模式
 */
public interface CustomerFactory {

    CustomerInterface getInstance();
}
/** 实现(一) 主流程 */
class MainCustomerFactory implements CustomerFactory{
    @Override
    public CustomerInterface getInstance() {
        return null;
    }
}
/** 实现(二) 预决策 */
class PreCustomerFactory implements CustomerFactory{
    @Override
    public CustomerInterface getInstance() {
        return null;
    }
}

class Test{
    public static void main(String[] args) {
        CustomerFactory factory = new MainCustomerFactory();
        CustomerInterface instance = factory.getInstance();
        
    }
}

抽象工厂(Abstract Factory)

定义

指通过工厂创建一个具有产品,而同一个产品内有多个相互依赖或相关的接口。

比较绕口,举一个实际例子:总共有4个流程,其中每个流程都有获取申请人和担保人的方法。

适用场景

  1. 客户端需要依赖产品的创建细节
  2. 强调一系列相关的产品对象需要一起被创建

优缺点

优点:
1.具体产品在应用城代码隔离,无需关心具体创建细节
2.将一系列的产品主放在一起创建。(如:主流程申请人和主流程担保人在一起创建)
缺点:
1.产品中扩展新产品困难,需要修改抽象类,如新增一个联系人则需要修改抽象工厂方法,所有的子类都需要实现
2.类结构复杂,增加了系统的抽象性、复杂度。

代码实现

我们代码实现定义中举的例子:
总共有4个流程,其中每个流程都有获取申请人和担保人的方法。
分析:
1.工厂目标:客户端需要根据自己的需要,获取4个不同的流程产品对象。
2. 每一个产品对象都分别由获取申请人信息和担保人信息的方法(申请人和担保人相关的接口)

代码实现

//客户接口,以及不同流程的实现类
public interface Customer {
}
class MainCustomer implements Customer{
}
class PreCustomer implements Customer{
}
//担保人接口,以及不同流程的实现类
public interface Guarantor {
}

class MainGuarantor implements Guarantor{
}

class PreGuarantor implements Guarantor{
}
// 抽象工厂
public abstract class TaskFactory {
    
    public void init(){
        //一些初始化操作
    }

    public abstract Customer getCustomer();

    public abstract Guarantor getGuarantor();
}

//主流程抽象工厂实现
class MainTaskFactory extends TaskFactory{

    @Override
    public Customer getCustomer() {
        return new MainCustomer();
    }

    @Override
    public Guarantor getGuarantor() {
        return new MainGuarantor();
    }
}

//预批流程工厂实现
class PreTaskFactory extends TaskFactory{
    @Override
    public Customer getCustomer() {
        return new PreCustomer();
    }

    @Override
    public Guarantor getGuarantor() {
        return new PreGuarantor();
    }
}

class Test {
    public static void main(String[] args) {
        TaskFactory factory = new MainTaskFactory();
        Customer customer = factory.getCustomer();
        Guarantor guarantor = factory.getGuarantor();
    }
}

桥接模式(Bridge Pattern)

定义

桥接模式又称双维度扩展模式,实际应用场景不太多。是将抽象部分与具体实现分离,使他们都可以独立变化。通过组合的方式将他们建立联系,而不是通过继承。

适用场景

一个类存在两个或多个独立变化的维度,且这两个维度都需要进行独立扩展。
举例:发送通知的方式有邮件、短信两种方式,而通过发送通知的方式又有加急、普通。

优缺点

优点:

1.分离抽象与具体
2.提高了系统的扩展性
3.复合开闭原则

缺点:

1.增加了系统的复杂度和设计难度
2.需要准确的识别系统中两个独立变化的维度(实际项目中难度较大)

代码实现

上面的例子【发送通知的方式有邮件、短信两种方式,而通过发送通知的方式又有加急、普通。】实现代码

public interface Message {
    void send(String message);
}

class EmailMessage implements Message{
    @Override
    public void send(String message) {
        System.out.println("发送邮件信息:"+message);
    }
}

class PhoneMessage implements Message{
    @Override
    public void send(String message) {
        System.out.println("发送手机短信信息:"+message);
    }
}

//抽象加急、普通短信桥接
public abstract class AbstractMessageBridge  {
    private Message message;
    public AbstractMessageBridge(Message message){
        this.message = message;
    }

    public void send(String message) {
        this.message.send(message);
    }
}
//普通短信
class NormalMessage extends AbstractMessageBridge{
    public NormalMessage(Message message) {
        super(message);
    }

    @Override
    public void send(String message) {
        super.send("[普通]"+message);
    }
}
//加急短信
class UrgentMessage extends AbstractMessageBridge{
    public UrgentMessage(Message message) {
        super(message);
    }

    @Override
    public void send(String message) {
        super.send("[加急]"+message);
    }
}
// 测试
class Test {
    public static void main(String[] args) {
        AbstractMessageBridge message = new UrgentMessage(new EmailMessage());
        message.send("紧急休假");

        AbstractMessageBridge message2 = new NormalMessage(new EmailMessage());
        message2.send("休假");

        AbstractMessageBridge message3 = new NormalMessage(new PhoneMessage());
        message3.send("休假");
    }
}

实际应用

数据库驱动与操作数据的API
设计模式之适配器模式、委派模式、访问者模式、工厂模式、桥接模式(双维度扩展)_第4张图片

观察者模式(Observer Pattern)

定义

观察者模式又称发布订阅模式(Publish/Subscribe),定义一种一对多的依赖关系,一个主题对象可以被多个观察者同时监听,每当主题对象状态变化时,多依赖的对象都会被通知到。

适用场景

  • 当一个或多个对象的变化依赖另一个对象的变化
  • 实现类似的广播机制,发布者无需知道具体的收听者,感兴趣的对象会自动接受该广播

传统实现

发布主题以及实现

public interface Subject<E> {

    void addObserver(Observer<E> observer);
    /**
     * 通知对象
     * @param event
     */
    void notify(E event);
}

public class NodeCodeSubject implements Subject<String> {
    private List<Observer<String>> observers = new ArrayList<>();
    
    == 通知所有观察者
    @Override
    public void notify(String event) {
        for (Observer<String> observer : observers) {
            observer.update(event);
        }
    }

	== 增加观察者的方法
    @Override
    public void addObserver(Observer<String> observer) {
        observers.add(observer);

    }
}

观察者实现

public interface Observer<E> {
    /**
     * 观察者对象变化
     * @param event
     */
    void update(E event);
}

public class NodeCodeObserver implements Observer<String>{

    @Override
    public void update(String event) {
        System.out.println("监听到节点变化了nodeCode:"+event);
    }
}


测试

public class Test {

    public static void main(String[] args) {
        NodeCodeObserver nodeCodeObserver = new NodeCodeObserver();
        NodeCodeObserver nodeCodeObserver2 = new NodeCodeObserver();

        Subject subject = new NodeCodeSubject();
        subject.addObserver(nodeCodeObserver);
        subject.addObserver(nodeCodeObserver2);

        subject.notify("end");
    }
}

Guava 实现

public class NodeCodeEvent {

    @Subscribe
    public void assignee(String nodeCode){
        System.out.println("监听到nodeCode改变:"+nodeCode);
    }

}

# 测试
public class Test {

    public static void main(String[] args) {

        EventBus eventBus = new EventBus();

        eventBus.register(new NodeCodeEvent());

        eventBus.post("evl");
        eventBus.post("visit");
    }
}

实际应用

监听节点的变化来分别处理不同的逻辑同时满足一个观察者可以监听多个节点的功能,分别实现如:刷新接口,人工派件等功能。

1.定义一个节点信息,用于存储基本信息以及后续扩展

public class NodeInfo {

    private Long caseId;
    private String nodeCode;
 // ignore getting/setting
}

2.定义观察者接口

继承 InitializingBean 为了结合Spring使用,提醒子类主动注册观察者

public interface NodeObserver extends InitializingBean {
    /**
     * 需要监听的节点
     * @return
     */
    List<String> registerCode();

    /**
     * 节点变化
     * @param nodeInfo
     */
    void nodeChange(NodeInfo nodeInfo);

}

3.定义一个节点管理器,用于实现注册和发布方法

public class NodeCodeManager {

	//注册的程序通过Key,Map存储到这里
    private static Map<String,List<NodeObserver>> map = new HashMap<>();

    public static void register(NodeObserver observer){
        for (String nodeCode : observer.registerCode()) {
            List<NodeObserver> list = null;
            if((list = map.get(nodeCode)) == null ){
                list = new ArrayList<>();
            }
            list.add(observer);
            map.put(nodeCode,list);
        }
    }

    /**
     * 节点变化,通知对应的节点
     * @param nodeInfo
     */
    public static void  notifyAll(NodeInfo nodeInfo){
        List<NodeObserver> list = map.get(nodeInfo.getNodeCode());
        if(list != null){
            for (NodeObserver nodeObserver : list) {
                nodeObserver.nodeChange(nodeInfo);
            }
        }
    }
}

4.应用一:实现指定的节点刷新接口

public class RefreshCoreService implements NodeObserver {

    @Override
    public List<String> registerCode() {
    	// 注册这两个节点作为这个类的观察节点,实现同时观察指定的多个接口
        return Arrays.asList("eval","vrf2");
    }

    @Override
    public void nodeChange(NodeInfo nodeInfo) {

        System.out.println("现在的节点是:"+nodeInfo.getNodeCode());
        System.out.println("开始刷新接口.....");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
    	//主动注册本实现作为观察者
        NodeCodeManager.register(this);
    }
}

5. 应用二、派件给对应的人(通过抽象类注册)

public abstract class AbstractNodeCodeObserver implements NodeObserver {

	//这个抽象类的作用是帮助子类注册作为观察者,子类无需在重复定义 
    @Override
    public void afterPropertiesSet() throws Exception {
        NodeCodeManager.register(this);
    }
}

@Service
public class AssigneeNodeObserver extends AbstractNodeCodeObserver {

    @Override
    public List<String> registerCode() {
        return Arrays.asList("vrf","evl","visit");
    }

    @Override
    public void nodeChange(NodeInfo nodeInfo) {
        System.out.println("案件:caseId:"+nodeInfo.getCaseId()+"开始派件:"+nodeInfo.getNodeCode());
    }

}


#测试,使用spring环境

@SpringBootTest
class SpbootApplicationTests {

	@Resource
	private AssigneeNodeObserver assigneeNodeObserver;

	@Test
	public void notifyAllTest() {

		NodeInfo nodeInfo = new NodeInfo();
		nodeInfo.setCaseId(1L);
		nodeInfo.setNodeCode("vrf");
		NodeCodeManager.notifyAll(nodeInfo);

	}

}

你可能感兴趣的:(设计模式,适配器模式,java)