资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

No2.大话设计模式学习之桥联、职责链、中介模式-创新互联

2.设计模式-part5
  • 2.10 桥接模式
    • 描述:桥接模式是将抽象部分与其实现部分分离,使它们都可以独立地变化
    • 好处1:可以避免创建者和具体产品之间的紧密耦合;
    • 好处2:避免了继承导致的类爆炸问题。
    • 好处3:具备灵活的可扩展性
    • 坏处1:将抽象和实现分离会增加设计的难度
    • eg:对于不同品牌的手机,软件基本无法兼容。因此如果手机需要增加软件,就需要针对不同品牌的手机分别实现软件功能
      • 场景:实现该问题的程序通常会采用继承方式设计,那么父类和子类之间会具有非常紧密的依赖关系,父类中的任何变化都会影响子类,子类继承的实现如果无法解决新需求就必须重写或替换父类。如此设计会导致类爆炸问题,并且扩展不灵活
      • 其它适用场景:
        • 对于使用较多类继承问题而导致紧耦合、扩展性差的系统。
        • 对于存在多个独立变化并需要灵活扩展维度的需求
      • 应用:
        • JDBC 规范和不同数据库厂商驱动的实现。
        • Spring 中可以根据客户的需求能够动态切换不同的数据源。
        • Nginx 的模块架构就应用了桥接模式,使用了nginx_module_t定义模块,结构体里有若干函数指针和扩展字段,然后桥接实现了丰富多彩的 core、conf、event、stream、http 等功能模块,搭建起整个 Nginx 框架
      • 步骤:
      • 核心思想使用合成/聚合原则代替类继承思想设计程序,从而降低耦合度、减少代码量。
        首先确定分类的角度,然后把这些实现独立出来,让它们互不干扰相互独立,从而减少耦合。需要注意的是能否找到合适的桥接点,如果没有就不必要非要使用桥接模式。
        包括以下四个角色:
        • Abstraction(抽象类):用于定义抽象类的接口,其中定义了一个具有关联关系的Implementor 的对象。
        • RefinedAbstraction(扩充抽象类):继承并实现抽象类中的接口,并在其中调用Implementor 对象的相关业务方法。
        • Implementor(实现类):用于定义实现类的接口,提供基本的业务方法供抽象类调用,以完成复杂的操作。
        • ConcreteImplementor(具体实现类):继承并实现 Implementor 的接口,在不同的具体实现类中提供不同的操作方法,通过向上转型的方式完成方法的调用。
      • 注意事项:
        • 将状态的转换放到具体的状态类内部
        • 通过上下文直接或通过参数改变状态,而不同的状态对应不同的行为
      • 代码实现:
        • HandsetSoft实现类:
        • public abstract class HandsetSoft {
              public abstract void run();
          }
        • HandsetSoft具体实现类:
        • public class HandsetGame extends HandsetSoft {
              @Override
              public void run() {
                  System.out.println("运行手机游戏");
              }
          }
          
          public class HandsetAddressList extends HandsetSoft {
              @Override
              public void run() {
                  System.out.println("运行手机通讯录");
              }
          }
        • HandsetBrand抽象类:
        • public abstract class HandsetBrand {
              protected HandsetSoft soft;
          
              public void SetHandsetSoft(HandsetSoft soft) {
                  this.soft = soft;
              }
          
              public abstract void run();
          }
        • HandsetBrand扩展抽象类:
        • public class HandsetBrandM extends HandsetBrand {
              @Override
              public void run() {
                  soft.run();
              }
          }
          
          public class HandsetBrandN extends HandsetBrand {
              @Override
              public void run() {
                  soft.run();
              }
          }
        • 调用方
        • public class Main {
              public static void main(String[] args) {
                  HandsetBrand ab;
                  ab = new HandsetBrandN();
          
                  ab.SetHandsetSoft(new HandsetGame());
                  ab.run();
          
                  ab.SetHandsetSoft(new HandsetAddressList());
                  ab.run();
          
                  ab = new HandsetBrandM();
          
                  ab.SetHandsetSoft(new HandsetGame());
                  ab.run();
          
                  ab.SetHandsetSoft(new HandsetAddressList());
                  ab.run();
              }
          }
      • 桥接模式通用结构示意图如下(引申)
        • image-20221017164911912
  • 2.11 职责链模式 collapsed:: true
    • 描述:职责链模式核心是解决服务中先后执行处理关系,从而降低请求发送者和接受者之间的耦合关系。类似于击鼓传花
    • 好处1:能够简化对象的相互连接,接收者和发送者都没有对方的明确信息,且链中的对象也不知道链的结构。
    • 好处1:避免了请求的发送者和接受者之间的耦合关系。
    • 好处3:能够随时修改请求的结构,增强了给对象指派职责的灵活性
    • 坏处1:请求可能到了链的末端都得不到处理,或者因为没有正确配置得不到处理。
    • 坏处2:较长的责任链可能会影响到系统的性能
    • eg:
      • Netty 中 Pipeline 与 ChannelHandler 通过责任链来组织代码逻辑。
      • Tomcat 中 Servlet 过滤器使用了责任链模式。
      • Spring 中切面编程和安全机制都使用了责任链模式。
      • 一个请求有多个对象可以处理,但每个对象的处理条件或权限不同
    • 场景:加薪、请假申请等需要层层审批的场景。比如向经理提加薪申请,经理没权利然后向总监上报,总监没权限然后向总经理汇报等
    • 步骤:
      • 将公司管理者的类别变成管理者的子类,可以通过多态性来化解分支带来的僵化。然后通过不同管理者之间建立管理关系实现请求的传递,使得请求的发送者和接收者解耦,可以让各服务模块更加清晰。处理者负责处理请求,客户只需要将请求发送到职责链,无需关心具体的处理细节。
      • Handler(请求类):用于定义一个处理请示的接口。
      • ConcreteHandler(具体处理者类):处理它所负责的请求,可访问它的后继者,如果能够处理就处理,否则就将请求转发给它的后继者
    • 代码实现:
      • Request类:
      • public class Request {
            private String requestType;
            private String requestContent;
            private int number;
        
            public String getRequestType() {
                return requestType;
            }
        
            public void setRequestType(String requestType) {
                this.requestType = requestType;
            }
        
            public String getRequestContent() {
                return requestContent;
            }
        
            public void setRequestContent(String requestContent) {
                this.requestContent = requestContent;
            }
        
            public int getNumber() {
                return number;
            }
        
            public void setNumber(int number) {
                this.number = number;
            }
        }
      • Manager类:
      • public abstract class Manager {
            protected String name;
            protected Manager superior;
        
            protected Manager(String name) {
                this.name = name;
            }
        
            public void SetSuperior(Manager superior) {
                this.superior = superior;
            }
        
            public abstract void requestApplications(Request request);
        }
      • ConcreteManager类:
      • public class GeneralManager extends Manager {
            protected GeneralManager(String name) {
                super(name);
            }
        
            @Override
            public void requestApplications(Request request) {
                if(request.getRequestType() == "请假"){
                    System.out.println(name + ":" + request.getRequestContent() + " 数量" + request.getNumber() + " 被批准" );
                }else if(request.getRequestType() == "加薪" && request.getNumber()<= 500) {
                    System.out.println(name + ":" + request.getRequestContent() + " 数量" + request.getNumber() + " 被批准" );
                }else {
                    System.out.println(name + ":" + request.getRequestContent() + " 数量" + request.getNumber() + " 再说吧" );
                }
            }
        }
        
        public class MajorDemo extends Manager {
            protected MajorDemo(String name) {
                super(name);
            }
        
            @Override
            public void requestApplications(Request request) {
                if(request.getRequestType() == "请假" && request.getNumber()<= 5) {
                    System.out.println(name + ":" + request.getRequestContent() + " 数量" + request.getNumber() + " 被批准" );
                }else {
                    if(superior != null) {
                        superior.requestApplications(request);
                    }
                }
            }
        }
        
        public class MajorDemo extends Manager {
            protected MajorDemo(String name) {
                super(name);
            }
        
            @Override
            public void requestApplications(Request request) {
                if(request.getRequestType() == "请假" && request.getNumber()<= 5) {
                    System.out.println(name + ":" + request.getRequestContent() + " 数量" + request.getNumber() + " 被批准" );
                }else {
                    if(superior != null) {
                        superior.requestApplications(request);
                    }
                }
            }
        }
      • 调用方
      • public class Main {
            public static void main(String[] args) {
                CommonManager jinli = new CommonManager("金利");
                MajorDemo zongjian = new MajorDemo("宗剑");
                GeneralManager zhongjingli = new GeneralManager("钟精励");
                jinli.SetSuperior(zongjian);
                zongjian.SetSuperior(zhongjingli);
        
                Request request = new Request();
                request.setRequestType("请假");
                request.setRequestContent("小菜请假");
                request.setNumber(1);
                jinli.requestApplications(request);
        
                Request request2 = new Request();
                request2.setRequestType("请假");
                request2.setRequestContent("小菜请假");
                request2.setNumber(4);
                jinli.requestApplications(request2);
        
                Request request3 = new Request();
                request3.setRequestType("加薪");
                request3.setRequestContent("小菜请求加薪");
                request3.setNumber(500);
                jinli.requestApplications(request3);
        
                Request request4 = new Request();
                request4.setRequestType("加薪");
                request4.setRequestContent("小菜请求加薪");
                request4.setNumber(1000);
                jinli.requestApplications(request4);
            }
        }
      • 职责链模式通用结构示意图如下(引申)
        • image-20221017164911912
  • 2.12 中介模式
    • 描述:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们的交互
    • 好处1:中介者减少了各个业务类的耦合,使得可以独立的改变和复用各个业务类和中介者类。
    • 好处2:中介者的实现类控制了集中化,把对象群交互的复杂性变为中介者的复杂性。
    • 好处3:当系统出现多对多交互复杂的对象群,可以考虑使用中介这模式。
    • 坏处1:中介者对象会较为复杂
    • eg:中介者模式一般应用于一组对象以定义良好但是复杂的方式进行通信的场合。以及想定制一个分布在多个类中的行为,而又不想生成太多的子类的场合
    • 问题描述:刚进公司的新人需求其他部门同事帮忙是有困难的,但是通过主管协调就会简单许多
      解决方案:
      • 通过中介者对象,可以将系统的网状结构变成以中介者为中心的星型结构,使得对象之间的耦合度变低、扩展性增强,系统的结构不会因为新对象的引入造成大量的修改工作。
      • Mediator(抽象中介者类):定义了同事对象到中介者对象的接口。
      • ConcreteMediator(具体中介者对象):实现抽象类的方法,知道所有具体同事类,并从具体同事接受消息,向其他具体同事发送命令。
      • Colleague(抽象同事类):用于定义抽象的同事对象,
      • ConcreteColleague(具体同事类):每个具体同事只知道自己的行为,而不了解其他同事类的情况,但是他们认识终结者对象。
    • 代码实现:
      • Mediator类:
      • abstract class Mediator {
            //定义一个抽象的发送消息方法,得到同事对象和发送消息
            public abstract void send(String message,Colleague colleague);
        }
      • ConcreteMediator类:
      • public class ConcreteMediator extends Mediator{
            public ConcreteColleague1 concreteColleague1;
            public ConcreteColleague2 concreteColleague2;
        
            public void setColleague1(ConcreteColleague1 value){
                this.concreteColleague1 = value;
            }
            public void setColleague2(ConcreteColleague2 value){
                this.concreteColleague2 = value;
            }
            @Override
            public void send(String message, Colleague colleague) {
                if(colleague == concreteColleague1){
                    concreteColleague2.notify(message);
                }else{
                    concreteColleague1.notify(message);
                }
            }
        }
      • Colleague类:
      • public class Colleague {
            protected Mediator mediator;
            // 构建方法,得到中介者对象
            public Colleague(Mediator mediator){
                this.mediator = mediator;
            }
        }
      • ConcreteColleague类:
      • public class ConcreteColleague1 extends Colleague {
            public ConcreteColleague1(Mediator mediator) {
                super(mediator);
            }
            public void send(String message){
                this.mediator.send(message,this);
            }
            public void notify(String message){
                System.out.println("同事1得到信息:"+message);
            }
        }
        
        public class ConcreteColleague2 extends Colleague {
            public ConcreteColleague2(Mediator mediator)
            {
                super(mediator);
            }
            public void send(String message)
            {
                this.mediator.send(message,this);
            }
            public void notify(String message)
            {
                System.out.println("同事2得到信息:"+message);
            }
        }
      • 调用方
      • public class main {
            public static void main(String[] args){
                ConcreteMediator m =new ConcreteMediator();
                ConcreteColleague1 c1 = new ConcreteColleague1(m);
                ConcreteColleague2 c2 = new ConcreteColleague2(m);
                m.setColleague1(c1);
                m.setColleague2(c2);
                c1.send("吃过饭了吗?");
                c2.send("没有呢,你打算请客?");
            }
        }
      • 中介者模式通用结构示意图如下(引申)
        • image-20221017164911912
  • 参考资料:《深入设计模式》

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧

成都创新互联是一家专业提供维西企业网站建设,专注与成都网站设计、网站建设、H5页面制作、小程序制作等业务。10年已为维西众多企业、政府机构等服务。创新互联专业网站制作公司优惠进行中。
文章标题:No2.大话设计模式学习之桥联、职责链、中介模式-创新互联
当前URL:http://cdkjz.cn/article/ccejgi.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

大客户专线   成都:13518219792   座机:028-86922220