我从不同的文章中学习了桥接模式,并根据我的理解实现了这一点。让我困惑的一件事是桥接模式说
BridgePattern将抽象与其实现解耦,以便两者可以独立变化
这句话的意思是什么?实现是否存在于单独的jar?
独立陈述的含义是什么?
考虑提供的日志开发文章,详细说明答案。
任何帮助都非常感谢。
BridgePattern将抽象与其实现解耦。
抽象和实现可以独立变化,因为具体类不直接实现抽象(接口)
实现从不引用抽象。抽象包含实现接口作为成员(通过组合)。
回到您关于[logaldev][4]文章中示例代码的问题:
形状是抽象的
三角形被重新定义抽象
颜色是实施者
RedColor是混凝土实施者
一个具体的形状对象:三角形扩展形状,但不实现颜色接口。
public class Triangle extends Shape{
}
RedColor和GreenColor实际上实现了Color接口。
混凝土形状对象(三角形)独立于实现抽象(即颜色接口)。
Shape tri = new Triangle(new RedColor());
这里三角形包含一个具体的Color对象(Comence)。如果Color抽象(接口)有变化,RedColor和GreenColor负责实现Color接口的抽象。
像三角形这样的形状不受颜色接口契约变化的影响。因此颜色接口可以独立变化。这是可能的,因为Shape持有使用组合而不是实现的契约。
更好地理解模式的示例代码:
示例代码:
/* Implementor interface*/
interface Gear{
void handleGear();
}
class VehicleAttributes{
String name;
String engineID;
String chasisNumber;
int seats;
int engineCapacity;
double height;
double length;
}
/* Concrete Implementor - 1 */
class ManualGear implements Gear{
public void handleGear(){
System.out.println("Manual gear");
}
}
/* Concrete Implementor - 2 */
class AutoGear implements Gear{
public void handleGear(){
System.out.println("Auto gear");
}
}
/* Abstraction (abstract class) */
abstract class Vehicle {
Gear gear;
/* Mutable state of Vehicle */
VehicleAttributes attributes;
public Vehicle(Gear gear){
this.gear = gear;
}
abstract void addGear();
public void setVehicleAttributes(VehicleAttributes attributes){
this.attributes = attributes;
}
}
/* RefinedAbstraction - 1*/
class Car extends Vehicle{
public Car(Gear gear){
super(gear);
// initialize various other Car components to make the car
}
public void addGear(){
System.out.print("Car handles ");
gear.handleGear();
}
}
/* RefinedAbstraction - 2 */
class Truck extends Vehicle{
public Truck(Gear gear){
super(gear);
// initialize various other Truck components to make the car
}
public void addGear(){
System.out.print("Truck handles " );
gear.handleGear();
}
}
/* Client program */
public class BridgeDemo {
public static void main(String args[]){
Gear gear = new ManualGear();
Vehicle vehicle = new Car(gear);
vehicle.addGear();
gear = new AutoGear();
vehicle = new Car(gear);
vehicle.addGear();
/* Create specific properties of Car in attributes */
//vehicle.setVehicleAttributes(attributes);
gear = new ManualGear();
vehicle = new Truck(gear);
vehicle.addGear();
/* Create specific properties of Truck in attributes */
//vehicle.setVehicleAttributes(attributes);
gear = new AutoGear();
vehicle = new Truck(gear);
vehicle.addGear();
/* Create specific properties of Truck in attributes */
//vehicle.setVehicleAttributes(attributes);
}
}
输出:
Car handles Manual gear
Car handles Auto gear
Truck handles Manual gear
Truck handles Auto gear
解释:
车辆
是一个抽象。Car
和Truck
是车辆
的两个具体实现。车辆
定义了一个抽象方法:addGear()
。Gear
是实现者接口ManualGear
和AutoGear
是Gear
车辆
包含实现者
接口而不是实现接口。实现者接口的Compositon
是这种模式的关键:它允许抽象和实现独立变化。Car
和Truck
定义抽象的实现(重新定义的抽象):addGear()
:它包含Gear
-手动
或Auto
桥接模式的用例:
这个语句的简单意思是,你可以在运行时切换抽象指向的实现器,一切都应该工作(就像在策略模式中一样;但是在策略模式中,只有策略是抽象的)。它也可以被理解为分离两个类,这样它们就不必相互了解,而不仅仅是它们的接口。
对我来说,Bridge并不是GOF圣经中最重要的DP,因为它主要是Strategy的衍生产品。作为其他一些没有老化的模式(工厂方法?),它意味着抽象类持有行为的继承比其他模式更多,因此不太普遍适用。
主要是战略在做大事,但战略的一个主要问题是战略通常需要了解其背景。
在某些语言中,这会导致策略被声明为上下文的朋友,或者策略被定义为Java中的内部类。
这意味着上下文通常最终会知道各种具体策略的存在。您可以通过使用setStrategy()函数来避免这种情况,但是由于效率原因(您希望直接操作上下文的数据结构),从具体策略到上下文的反向依赖通常会保留下来。
Bridge解决了这个问题,因为Strategy的上下文现在是抽象的,但仍然是一个先验的类,因为它至少有Strategy的代码。它通常应该定义一个足以让具体策略使用的访问API,可能有洞,即抽象方法。你在AbstractStragey上的操作签名中出现了AbstractContext,你就很好了。
因此,在我看来,Bridge通过使Context足够具体以使策略工作来完成策略,但仍然足够抽象,以至于它可以正交地细化具体策略(在实现具体策略实际使用的上下文的抽象API时具有反馈效果)。
一种更简单的看待桥的方法是说AbstractStrategy操作应该始终将抽象作为参数,而不是真正了解它们的上下文。
要更准确地回答OP问题:
这句话的意思是什么?实现是否存在于单独的jar?
是的,实际上,通常你可以在一个包“base”(tey可以是接口)中定义抽象和实现器。具体的实现器可以各自驻留在一个包“implXX”中。具体的上下文可以驻留在单独的包“contXX”中。依赖图中没有循环,每个人都依赖于base,新的“contXX”和“implXX”可以独立定义(它们之间根本没有依赖关系),因此OP中的粗体语句。
独立陈述的含义是什么?
想象一下eclipse中的编辑器插件;它必须处理按钮和点击上的操作(就像策略一样),但策略需要做的实际操作是作用于编辑器状态本身(例如“突出显示文本”)。您以抽象的方式定义编辑器拥有的内容,包括它具有用于clics和keypress的Handler以及突出显示和导航功能,即使这些功能也可以被具体的编辑器覆盖(flash而不是突出显示)。这是一座桥梁,您可以独立定义新的编辑器和新的处理程序。
通过一些依赖注入(例如Google guice)或一些手动工厂代码或组件方向来从外部干净地设置Strategy,您可以获得应用程序各个部分的非常低的耦合。
考虑提供的日志开发文章,详细说明答案。
老实说,我认为这不是DP的最佳应用,因为颜色实现似乎不太关心它们的上下文。你应该在这里使用装饰器,因为颜色是形状的独立关注点。
看看这些幻灯片,了解装饰器的解决方案(部分是法语,抱歉)。https://www-licence.ufr-info-p6.jussieu.fr/lmd/licence/2015/ue/3I002-2016fev/cours/cours-9.pdf(幻灯片16-18)基于这里介绍的示例:https://www-licence.ufr-info-p6.jussieu.fr/lmd/licence/2015/ue/3I002-2016fev/cours/cours-4.pdf幻灯片10到15。
在这个例子中,如果“updateInertie”是Forme的成员,我们需要Bridge,这听起来并不荒谬。同样,Bridge更多地是作为其他模式的组合出现的。