我知道之前有人问过这个问题(例如,桥接模式和策略模式有什么区别?)。
然而,能否有人用清晰明了的例子来解释一下它们之间的区别,并在什么情况下必须选择其中一个而不是另一个?更少的概念理论,更多实际的“现实生活”场景将不胜感激。
我知道之前有人问过这个问题(例如,桥接模式和策略模式有什么区别?)。
然而,能否有人用清晰明了的例子来解释一下它们之间的区别,并在什么情况下必须选择其中一个而不是另一个?更少的概念理论,更多实际的“现实生活”场景将不胜感激。
我知道这很难解释。许多使用并理解它的人都很难向新手解释。
对于像我这样以类比思考的人:
因此,策略是一种一维概念。想象一下一维策略数组供选择。
策略模式就像一个拥有多种工具来清理管道的管工。每次的任务都是相同的,即清理管道。但在不同情况下,他选择用来完成任务的工具可能会不同。也许他会尝试一种方法,如果不起作用就尝试另一种方法。
在这个类比中,“清理管道”是将实现其中一种策略的方法。蛇刷,电动钻头和Draino是具体的策略,而管工则是包含该方法的类(在大多数图表中标记为“上下文”)。
或者,您可以将其看作是多位螺丝刀上的可互换位。
它们旨在在运行时更改,以适应手头的工作,即拧紧某物。
因此,桥接是一个二维概念。想象一下一个维度(行)是需要实现的方法列表,而第二个维度(列)是将实现每个方法的实现者。
桥接模式就像一个人可以通过许多方式进行通信(电子邮件,短信,Google语音,电话,Skype),并且有许多设备可以使用这些不同的方式进行通信-个人电脑,平板电脑和智能手机。
各种通信方式(电子邮件,短信,电话)将成为抽象接口上的方法,让我们称之为“CommunicationDevice”。在这个模式中,CommunicationDevice是实现者。此类比喻中的每个设备(PC,平板电脑,智能手机)都是具体实现者,实现所有这些方法(电子邮件,短信,电话)。
Windows中的另一个可用桥接模式的示例是ODBC或OLEDB数据库驱动程序模块。它们都在同一标准“数据库驱动程序”接口上实现了各种方法,但它们以不同的方式实现该接口。即使您使用相同的数据库,比如SQL Server,仍然有不同的驱动程序可以与SQL Server通信,虽然在底层采用了不同的方式。
该模式让执行算法与使用它的客户端独立变化。即,不是为给定情况下执行的固定算法,而是允许在运行时从众多算法中选择一个进行执行。这涉及将算法从其宿主类中移除并放入单独的类中。
例如,假设某人想要从一个城市到另一个城市,那么他有几种选择:乘坐公共汽车、租赁汽车、乘坐火车等。因此,选择的每种交通方式都会转化为一个单独的算法来执行。所选的交通方式将取决于运行时决定的各种因素(成本、时间等)。换句话说,选择用于执行的策略将在运行时决定。
另一个例子,假设要实现一个SortedList
类(主控制器),该类基于策略
进行排序。策略是用于排序的方法(如MergeSort、QuickSort)。
主要区别(尽管两种模式具有相同的UML)是,与桥接模式(它是一种结构模式)不同,策略模式是一种行为模式。结构模式提供了对象组合、关联或继承形成更大对象的方式,即它们关注对象组合。而行为模式处理算法或业务逻辑(而不是对象创建本身),即它们关注对象之间的协作。
请注意,大多数算法可以实现为静态或单例类,仅需要创建单个实例(即,在设置策略时不会每次调用new
)。
仔细查看两种模式的实现将揭示,在桥接模式中,首先创建对象的具体实现,然后进行调用。
// Set implementation and call
// i.e. Returns (creates) the concrete implementation of the object,
// subsequently operation is called on the concrete implementation
ab.Implementor = new ConcreteImplementorA();
ab.Operation();
在策略模式中,不会直接使用算法的具体实现,而是创建上下文来执行策略。
// Set the context with a strategy
// i.e. Sets the concrete strategy into the context, concrete implementation of the class not
// directly available as a data object (only the algorithm is available).
context = new Context (new ConcreteStrategyA());
context.contextInterface();
// Strategy can be reused instead of creating a new instance every time it is used.
// Sort example
MergeSort mergeSort = new MergeSort();
QuickSort quickSort = new QuickSort();
...
context = new Context (mergeSort);
context.Sort();
...
context = new Context (quickSort);
context.Sort();
...
context = new Context (mergeSort);
context.Sort();
桥接模式可以让我们根据当前情况重新实现运行业务结构,而策略模式则可以让我们实现各种业务策略并将其封装起来,根据情况或同时使用它们。
两者之间的主要区别在于使用桥接模式,我们可以改变整个结构,但是使用策略模式,我们能够并行地改变我们的业务策略。
我根据自己的理解详细阐述了下面两个非常重要的设计模式。 请仔细阅读,我认为这将清楚地解释两者的区别。
GoF建议的桥接模式的意义是将组件的实现与其抽象分离。
想象一种情况,一个组件已经实现,并且按照您的业务需求正常运行。突然组织改变了他们的业务策略。为此,您需要更改或重新实现组件。在这种情况下,你会怎么做?改变之前几年运行良好的组件,还是创建新组件?在这种情况下,桥接模式能够很好地处理场景。为了更好地理解,请参见下面的示例。
// Main component
public interface Ibridge
{
void function1();
}
// Already Implemented that are currently being using
public class Bridge1 : Ibridge
{
public void function1()
{
Console.WriteLine("Implemented function from bridge 1");
}
}
//New Implementation as per Organisation needs
public class Bridge2 : Ibridge
{
public void function1()
{
Console.WriteLine("Implemented function from bridge2");
}
}
//Abstract Calling functionalities
public interface IAbstractBridge
{
void CallFunc1();
}
// implementation of calling implemented component at a time
public class AbstractBridge:IAbstractBridge
{
protected Ibridge _ibridge;
public Ibridge Ibridge
{
set { _ibridge = value; }
}
public void CallFunc1()
{
this._ibridge.function1();
}
}
class Program
{
static void Main(string[] args)
{
AbstractBridge abp = new AbstractBridge();
/*
here you see that now being using the previous implemented component.
but need change newly implemented component so here we need just changed
the implementation of component, please see below
*/
//Commented old one
abp.Ibridge = new Bridge1();
//using new one just change the "Bridge1" to "Bridge2"
abp.Ibridge = new Bridge2();
abp.CallFunc1();
}
}
GoF提出的策略模式是指:定义一系列算法,将每个算法封装起来,并使它们可以互换。策略让算法独立于使用它的客户端而变化。
假设一个购物中心的所有者想要根据不同的场合为顾客提供不同的折扣优惠,并且随时可以从折扣模式切换到正常模式或相反,那么如何处理这种情况呢?在这种情况下,策略模式可以很好地处理这种情况。请看下面的示例以更好地理解。
public interface ISellingStrategy
{
void selling();
}
public class BasicStrategy : ISellingStrategy
{
public void selling()
{
Console.WriteLine("Buy Three get 5% discount.");
}
}
public class ChrismasStrategy : ISellingStrategy
{
public void selling()
{
Console.WriteLine("Buy Three get one offer + extra 5% discount.");
}
}
public class HoliFestiveStrategy : ISellingStrategy
{
public void selling()
{
Console.WriteLine("Buy two get one offer + extra 5% discount.");
}
}
public class DurgapuljaStrategy : ISellingStrategy
{
public void selling()
{
Console.WriteLine("Buy one get one offer + extra 5% discount.");
}
}
public class Billing
{
private ISellingStrategy strategy;
public void SetStrategy(ISellingStrategy _strategy)
{
this.strategy = _strategy;
}
public void ApplyStrategy()
{
strategy.selling();
Console.WriteLine("Please wait offer is being applying...");
Console.WriteLine("Offer is now Applied and ready for billing..");
}
}
public class BillingFactory
{
public static Billing CreateBillingObject()
{
return new Billing();
}
}
class Program
{
static void Main(string[] args)
{
Billing billing = BillingFactory.CreateBillingObject();
billing.SetStrategy(new BasicStrategy());
billing.ApplyStrategy();
Console.ReadLine();
}
}
class Sorter abstract
{
virtual void Sort() = 0;
}
// MergeSorter IS A Sorter
class MergeSorter : public Sorter
{
virtual void Sort() override;
}
class SortStrategy abstract
{
virtual void Sort() = 0;
}
// Sorter HAS A SortStrategy
class Sorter
{
Sorter(SortStragety *strategy) : mStrat(strategy) {}
void Sort() {mStrat->Sort();}
SortStrategy *mStrat;
}
http://www.php5dp.com/category/design-patterns/bridge/
并且
你会发现许多例子适用于这两种模式,可能会有所帮助。让我引述一下链接问题的答案。
桥接模式是一种结构模式,它提出了如何构建项目组件的思路。它用于隐藏两个抽象级别。维基百科上的示例代码(http://en.wikipedia.org/wiki/Bridge_pattern)以最明确的方式解释了它。
策略模式是一种动态模式。当任何野函数都可以实现要求时,就使用策略模式。例如,任何允许开发和安装插件的程序。在维基百科页面(http://en.wikipedia.org/wiki/Strategy_pattern)上,ConcreteStrategyAdd、ConcreteStrategySubtract等是在ConcreteStrategy类中使用的插件。任何实现Strategy接口的方法都可以在那里使用。
策略模式:
策略模式 是一种行为设计模式,用于在算法族之间切换。
该模式包含一个抽象的策略 接口 和许多该接口的具体策略实现(算法)。
应用程序仅使用策略 接口。根据某些配置参数,将 具体策略 标记到 接口 上。
桥接模式:
然而,请有人使用明确的示例解释两者之间的区别,并在何种情况下必须选择其中之一?
请参考以下文章以了解策略模式和桥接模式的用例:
简单说明:
使用策略模式通过将一种策略替换为另一种策略来动态更改实现。
一个真实的例子是:航空公司在淡季提供折扣。在高峰期间,只需使用无折扣策略替换票价折扣策略即可。
在抽象和实现未在编译时确定且可以独立变化时使用桥接模式
汽车行业中的一个真实世界例子:不同类型的齿轮可以组装成不同类型的汽车。汽车和齿轮的规格和实现都可以独立变化。