zoukankan      html  css  js  c++  java
  • 18、桥接模式

    桥接模式:

    桥接模式(Bridge),将抽象部分与它的实现部分分离,使它们都可以独立地变化。(实现系统可能有多角度分类,每一种分类都有可能变化(只用继承会造成类的大量增加,不能满足开放——封闭原则),那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合)

    抽象与它的实现分离,并不是说让抽象类与其派生类分离,实现指的是抽象类和它的派生类用来实现自己的对象。例:手机既可以按照品牌来分类,也可以按照功能来分类,具体可以参考下面实例:

    按品牌分类:

    按软件实现分类:

    由于实现的方式有多种,桥接模式的核心意图就是把这些实现独立出来,让他们各自地变化,这就使得每种实现的变化不会影响其他实现,从而达到应对变化的目的。

    桥接模式实现:

    这样就解决了按品牌分类或按软件分类增加新品牌/软件时的复杂性和代码不可复用性。

    桥接模式UML结构图:

    例(手机软件):

    	//手机品牌
        abstract class HandsetBrand
        {
            protected HandsetSoft soft;
    
            //设置手机软件
            public void SetHandsetSoft(HandsetSoft soft)
            {
                this.soft = soft;
            }
            //运行
            public abstract void Run();
            
    
        }
    
        //手机品牌N
        class HandsetBrandN : HandsetBrand
        {
            public override void Run()
            {
                soft.Run();
            }
        }
    
        //手机品牌M
        class HandsetBrandM : HandsetBrand
        {
            public override void Run()
            {
                soft.Run();
            }
        }
    
        //手机品牌S
        class HandsetBrandS : HandsetBrand
        {
            public override void Run()
            {
                soft.Run();
            }
        }
    
    
        //手机软件
        abstract class HandsetSoft
        {
    
            public abstract void Run();
        }
    
        //手机游戏
        class HandsetGame : HandsetSoft
        {
            public override void Run()
            {
                Console.WriteLine("运行手机游戏");
            }
        }
    
        //手机通讯录
        class HandsetAddressList : HandsetSoft
        {
            public override void Run()
            {
                Console.WriteLine("运行手机通讯录");
            }
        }
    
        //手机MP3播放
        class HandsetMP3 : HandsetSoft
        {
            public override void Run()
            {
                Console.WriteLine("运行手机MP3播放");
            }
        }
    
    	class Program
        {
            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();
    
                Console.Read();
            }
        }
    

    例(发送提示消息):

    消息分成普通消息、加急消息和特急消息多种,不同的消息类型,业务功能处理是不一样的,比如加急消息是在消息上添加加急,而特急消息除了添加特急外,还会做一条催促的记录,多久不完成会继续催促。从发送消息的手段上看,又有系统内短消息、手机短消息、邮件等等。

    全部采用继承,不使用桥接模式的UML图(如果继续扩展消息类型或者发送方式将会十分繁琐):

    例:继续添加发送手机消息的处理方式(这个时候代码结构就逐渐开始变得复杂):

    桥接模式实现:

    代码:

    public interface MessageImplementor {     
        public void send(String message,String toUser);     
    }  
    
    public class MessageEmail implements MessageImplementor {
    	public void send(String message, String toUser) {
    		System.out.println("使用Email的方式,发送消息'" + message + "'给" + toUser);
    	}
    }
    
    public class MessageMobile implements MessageImplementor {
    
    	public void send(String message, String toUser) {
    		System.out.println("使用手机短消息的方式,发送消息'" + message + "'给" + toUser);
    	}
    }
    
    public class MessageSMS implements MessageImplementor {
    	public void send(String message, String toUser) {
    		System.out.println("使用站内短消息的方式,发送消息'" + message + "'给" + toUser);
    	}
    }
    
    public abstract class AbstractMessage {
    	protected MessageImplementor impl;
    
    	public AbstractMessage(MessageImplementor impl) {
    		this.impl = impl;
    	}
    
    	public void sendMessage(String message, String toUser) {
    		this.impl.send(message, toUser);
    	}
    }
    
    public class CommonMessage extends AbstractMessage {
    	public CommonMessage(MessageImplementor impl) {
    		super(impl);
    	}
    
    	public void sendMessage(String message, String toUser) {
    		super.sendMessage(message, toUser);
    	}
    }
    
    public class UrgencyMessage extends AbstractMessage {
    	public UrgencyMessage(MessageImplementor impl) {
    		super(impl);
    	}
    
    	public void sendMessage(String message, String toUser) {
    		message = "加急:" + message;
    		super.sendMessage(message, toUser);
    	}
    
    	public Object watch(String messageId) {
    		return null;
    	}
    }
    
    public class SpecialUrgencyMessage extends AbstractMessage {
    	public SpecialUrgencyMessage(MessageImplementor impl) {
    
    		super(impl);
    	}
    
    	public void hurry(String messageId) {
    		// 执行催促的业务,发出催促的信息
    	}
    
    	public void sendMessage(String message, String toUser) {
    		message = "特急:" + message;
    		super.sendMessage(message, toUser);
    	}
    }
    
    /*
     * 意图:将抽象部分与实现部分分离,使它们都可以独立的变化。
     * 主要解决:在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。
     * 何时使用:实现系统可能有多个角度分类,每一种角度都可能变化。
     * 如何解决:把这种多角度分类分离出来,让它们独立变化,减少它们之间耦合。
     * 关键代码:抽象类依赖实现类。
     */
    
    /*
     * 该发送消息的实例由于发送方式的可扩展性和发送级别(普通,加急,特急等)的可扩展性,使用继承并不灵活
     * 考虑使用桥接模式:分离这两部分,使它们独立变化,减少它们之间的耦合(低耦合)
     * 注意事项:有时候我们看待问题的角度不同,可能采取的分离措施也会有所不同,因此代码结构也会有所不同
     *(这种过于复杂的情况下桥接模式就不再能说很合适,因为桥接模式本身就加剧了代码的复杂性,较于继承更加难以理解一些,但是使用得当则会让代码结构更加简洁清晰)
     */
    
    public class Client {
    	public static void main(String[] args) {
    		
    		MessageImplementor impl = new MessageSMS();  //接口下的发送方式定义
    		AbstractMessage m = new CommonMessage(impl);  //发送消息的方式实现
    		
    		m.sendMessage("请喝一杯茶", "小李");
    		m = new UrgencyMessage(impl);
    		m.sendMessage("请喝一杯茶", "小李");
    		m = new SpecialUrgencyMessage(impl);
    		m.sendMessage("请喝一杯茶", "小李");
    		
    		impl = new MessageMobile();
    		m = new CommonMessage(impl);
    		m.sendMessage("请喝一杯茶", "小李");
    		m = new UrgencyMessage(impl);
    		m.sendMessage("请喝一杯茶", "小李");
    		m = new SpecialUrgencyMessage(impl);
    		m.sendMessage("请喝一杯茶", "小李");
    		
    		impl = new MessageEmail();
    		m = new CommonMessage(impl);
    		m.sendMessage("请喝一杯茶", "小李");
    		m = new UrgencyMessage(impl);
    		m.sendMessage("请喝一杯茶", "小李");
    		m = new SpecialUrgencyMessage(impl);
    		m.sendMessage("请喝一杯茶", "小李");
    	}
    }
    
  • 相关阅读:
    RefreshParenwin 打开子窗体 并回发
    DataAdapter插入数据
    GridViewTotal
    滚动截图软件
    十个随机数排列(vb代码)
    SQL查询效率100w数据查询只要1秒
    ASP.NET操纵EXCEL导入SQL SERVER数据库的代码
    ajax blogs !good!
    轻松掌握Ajax.net系列教程
    asp.net 性能优化 Write less, do more...
  • 原文地址:https://www.cnblogs.com/study-hard-forever/p/13166709.html
Copyright © 2011-2022 走看看