zoukankan      html  css  js  c++  java
  • 设计模式--桥接模式Bridge(结构型)

    一、概述

    在软件系统中,某些类型由于自身的逻辑,它具有两个或者多个维度的变化,如何应对这种“多维度的变化”,就可以利用桥接模式。

    引例:

    设想如果要绘制矩形、圆形、椭圆、正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色、绿色、蓝色等,此时至少有如下两种设计方案:

    •第一种设计方案是为每一种形状都提供一套各种颜色的版本。

    •第二种设计方案是根据实际需要对形状和颜色进行组合。 

    对于有两个变化维度(即两个变化的原因)的系统,采用方案二来进行设计系统中类的个数更少,且系统扩展更为方便。设计方案二即是桥接模式的应用。桥接模式将继承关系转换为关联关系,从而降低了类与类之间的耦合,减少了代码编写量。

    二、UML图

    抽象类(Abstraction):定义抽象类的接口,维护一个指向Implementor类型对象的指针

    扩充抽象类(RefinedAbstraction):扩充由Abstraction定义的接口

    实现类接口(Implementor):定义实现类的接口,该接口不一定要与
    Abstraction的接口完全一致;事实上这两个接口可以完全不同。一般来讲, Implementor接口仅提供基本操作,而 Abstraction则定义了基于这些基本操作的较高层次的操作。

    具体实现类(ConcreteImplementor):实现Implementor接口并定义它的具体实现。

    三、例子

    拿汽车在路上行驶的来说。即有小汽车又有公共汽车,它们都不但能在市区中的公路上行驶,也能在高速公路上行驶。这你会发现,对于交通工具(汽车)有不同的类型,然而它们所行驶的环境(路)也在变化,在软件系统中就要适应两个方面的变化?怎样实现才能应对这种变化呢?

    传统做法:

    namespace CarRunOnRoad
    {
        //路的基类;
        public  class Road
        {
            public virtual void Run()
            {
                Console.WriteLine("在路上");
            }
        }
        //高速公路;
        public class SpeedWay : Road
        {
            public override void Run()
            {
                Console.WriteLine("高速公路");
            }
        }
        //市区街道;
        public class Street : Road
        {
            public override void Run()
            {
                Console.WriteLine("市区街道");
            }
        }
        //小汽车在高速公路上行驶;
        public class CarOnSpeedWay : SpeedWay
        {
            public override void Run()
            {
                Console.WriteLine("小汽车在高速公路上行驶");
            }
        }
        //公共汽车在高速公路上行驶;
        public class BusOnSpeedWay : SpeedWay
        {
            public override void Run()
            {
                Console.WriteLine("公共汽车在高速公路上行驶");
            }
        }
        //小汽车在市区街道上行驶;
        public class CarOnStreet : Street
        {
            public override void Run()
            {
                Console.WriteLine("汽车在街道上行驶");
            }
        }
        //公共汽车在市区街道上行驶;
        public class BusOnStreet : Street
        {
            public override void Run()
            {
                Console.WriteLine("公共汽车在街道上行驶");
            }
        }
       
    }
    
    static void Main(string[] args)
            {
                //小汽车在高速公路上行驶
                CarOnSpeedWay Car = new CarOnSpeedWay();
                Car.Run();
    
                Console.WriteLine("===========================");
    
                //公共汽车在街道上行驶
                BusOnStreet Bus = new BusOnStreet();
                Bus.Run();
    
                Console.Read();
            }

    这种设计存在很多问题,首先它在遵循开放-封闭原则的同时,违背了类的单一职责原则,即一个类只有一个引起它变化的原因,而这里引起变化的原因却有两个,即路类型的变化和汽车类型的变化;其次是重复代码会很多,不同的汽车在不同的路上行驶也会有一部分的代码是相同的;再次是类的结构过于复杂,继承关系太多,难于维护,最后最致命的一点是扩展性太差。如果变化沿着汽车的类型和不同的道路两个方向变化,我们会看到这个类的结构会迅速的变庞大。

    采用桥接模式

    namespace CarRunOnRoad_Bridge_
    {
    
        //抽象路
        public abstract class AbstractRoad
        {
            protected AbstractCar car;
            public AbstractCar Car
            {
                set
                {
                    car = value;
                }
            }
    
            public abstract void Run();
        }
    
        //高速公路
        public class SpeedWay : AbstractRoad
        {
            public override void Run()
            {
                car.Run();
                Console.WriteLine("高速公路上行驶");
            }
        }
    
        //市区街道
        public class Street : AbstractRoad
        {
            public override void Run()
            {
                car.Run();
                Console.WriteLine("市区街道上行驶");
            }
        }
    }
    
    namespace CarRunOnRoad_Bridge_
    {
        //抽象汽车 
        public abstract class AbstractCar
        {
            public abstract void Run();
        }
    
        //小汽车;
        public class Car : AbstractCar
        {
            public override void Run()
            {
                Console.Write("小汽车在");
            }
        }
    
        //公共汽车
        public class Bus : AbstractCar
        {
            public override void Run()
            {
                Console.Write("公共汽车在");
            }
        }
    }
    
    static void Main(string[] args)
           {
               //小汽车在高速公路上行驶;
               AbstractRoad Road1 = new SpeedWay();
               Road1.Car = new Car();
               Road1.Run();
               Console.WriteLine("=========================");
    
               //公共汽车在高速公路上行驶;
               AbstractRoad Road2 = new SpeedWay();
               Road2.Car = new Bus();
               Road2.Run();
    
              
    
               Console.Read();
           }

    参考:

    http://www.cnblogs.com/houleixx/archive/2008/02/23/1078877.html

    http://blog.csdn.net/hguisu/article/details/7529194

  • 相关阅读:
    5 Things Every Manager Should Know about Microsoft SharePoint 关于微软SharePoint每个经理应该知道的五件事
    Microsoft SharePoint 2010, is it a true Document Management System? 微软SharePoint 2010,它是真正的文档管理系统吗?
    You think you use SharePoint but you really don't 你认为你使用了SharePoint,但是实际上不是
    Introducing Document Management in SharePoint 2010 介绍SharePoint 2010中的文档管理
    Creating Your Own Document Management System With SharePoint 使用SharePoint创建你自己的文档管理系统
    MVP模式介绍
    权重初始化的选择
    机器学习中线性模型和非线性的区别
    神经网络激励函数的作用是什么
    深度学习中,交叉熵损失函数为什么优于均方差损失函数
  • 原文地址:https://www.cnblogs.com/justkong/p/6229498.html
Copyright © 2011-2022 走看看