简体   繁体   English

这是java中Bridge模式的正确实现吗?

[英]Is this a correct implementation of Bridge pattern in java?

I'm trying to improve my knowledge of design patterns, and I am a little bit confused with the Bridge pattern. 我正在努力提高我对设计模式的了解,而且我对Bridge模式有点困惑。 Below you can see my example: 下面你可以看到我的例子:

public interface Animal {
    public abstract void eat();
    public abstract void move();
}


public class Jaguar implements Animal{

    @Override
    public void eat() {
        System.out.println("The Jaguar eats meat");
    }

    @Override
    public void move() {
        System.out.println("The Jaguar runs");
    }
 }

public class Kangaroo implements Animal{

    @Override
    public void eat() {
        System.out.println("THe Kangaroo eats grass and other vegetables");
    }

    @Override
    public void move() {
        System.out.println("The Kangaroo hops around :)");
    }

}

public abstract class Environment {

    private Animal animal;

    public Environment(Animal animal){
        this.animal = animal;
    }

    public void someAnimalEats(){
        this.animal.eat();
    }

    public void someAnimalMoves(){
        this.animal.move();
    }

    public abstract void environmentPolutionStatus();
}


public class Australia extends Environment{

    public Australia(Animal animal) {
        super(animal);
    }

    @Override
    public void environmentPolutionStatus() {
        System.out.println("Australia is in good shape as far as polution is concerned.");
    }

}


public class Africa extends Environment{

    public Africa(Animal animal) {
        super(animal);
    }

    @Override
    public void environmentPolutionStatus() {
        System.out.println("Africa looks pretty good, however the hunting is kind of bad");

    }

}

public class BridgePatternMain {
    public static void main(String[] args){
        Environment australiaKangaroo = new Australia(new Kangaroo());
        Environment australiaJaguar = new Australia(new Jaguar());
        Environment africaKangaroo = new Africa(new Kangaroo());
        Environment africaJaguar = new Africa(new Jaguar());

        australiaKangaroo.environmentPolutionStatus();
        australiaKangaroo.someAnimalEats();
        australiaKangaroo.someAnimalMoves();

        australiaJaguar.environmentPolutionStatus();
        australiaJaguar.someAnimalEats();
        australiaJaguar.someAnimalMoves();

        africaKangaroo.environmentPolutionStatus();
        africaKangaroo.someAnimalEats();
        africaKangaroo.someAnimalMoves();

        africaJaguar.environmentPolutionStatus();
        africaJaguar.someAnimalEats();
        africaJaguar.someAnimalMoves();
    }
}

My questions: 我的问题:

  1. Is this a correct Bridge pattern? 这是一个正确的桥模式吗?
  2. Is it possible to have Bridge pattern if interfaces are replaced by abstract classes (I saw this approach in this tutoarial http://www.newthinktank.com/2012/10/bridge-design-pattern-tutorial/ ). 如果接口被抽象类替换,是否可能有Bridge模式(我在这个tutoarial http://www.newthinktank.com/2012/10/bridge-design-pattern-tutorial/中看到了这种方法)。 But according to this one ( https://dzone.com/articles/design-patterns-bridge ) is seems like Animal in my case shouldn't be an abstract class.. 但根据这个( https://dzone.com/articles/design-patterns-bridge )似乎在我的情况下动物应该不是一个抽象类..
  3. Is it necessary to have the methods someAnimalEats() and someAnimalMoves() in the Environment class? 是否有必要在Environment类中使用someAnimalEats()someAnimalMoves()方法? More precisely, is it mandatory to have in this class methods corresponding to each of the methods from the Animal interface? 更准确地说,是否必须在此类方法中使用与Animal接口中的每个方法相对应的方法?

Many Thanks! 非常感谢!

  1. The domain you demonstrate (animals and their environments) is not really a good use case for the bridge pattern. 你展示的领域(动物及其环境)对于桥梁模式来说并不是一个很好的用例。 It has a pretty specific purpose: to separate an abstraction (including extensions of that abstraction) from implementations (again possibly including extensions). 它有一个非常特定的目的:将抽象(包括该抽象的扩展)与实现(可能还包括扩展)分开。 One of the key characteristics is that the abstraction references the implementation (which is the 'bridge' in the name) rather than the implementation extending or implementing the abstraction. 其中一个关键特性是抽象引用实现(名称中的“桥”),而不是扩展或实现抽象的实现。 Generally the concrete implementation is decided by the client at run-time. 通常,具体实现由客户端在运行时决定。

It's not easy to think of a natural use case for bridge that models real world objects (like animals and environments). 想象一下模拟现实世界物体(如动物和环境)的桥梁的自然用例并不容易。 Easier is to think of class that is designed to perform some function. 更容易想到旨在执行某些功能的类。

// abstraction 
abstract class Logger {
    protected final LogOutputter outputter;
    public abstract void log(String message);
}

// abstraction extension
class ErrorLogger extends Logger {
    public void log(String message) {
        outputter.output("Error: " + message);
    }
}

// implementation interface
interface LogOutputter {
    void output(String message);
}

// implementation extensions
class FileLogOutputter implements LogOutputter ...
class ConsoleLogOutputter implements LogOutputter ...

And the client might do something like: 客户端可能会执行以下操作:

Logger logger = new ErrorLogger(new FileLogOutputter("errors.log"));
  1. I would suggest the class / interface combinations I used in this example are fairly typical. 我建议我在这个例子中使用的类/接口组合是相当典型的。 You could make the abstraction and interface but given the point of the bridge is to reference the implementation it makes it easier to make it an abstract class. 您可以创建抽象和接口,但考虑到桥接点是引用实现,它使它更容易使它成为一个抽象类。

  2. Hopefully the example also answers this: you could have similar methods in the abstraction and implementation but it's certainly not necessary. 希望这个例子也回答这个问题:你可以在抽象和实现中使用类似的方法,但这肯定没有必要。 One of the interesting and useful aspects of the pattern is that different independent characteristics (in this example, what is logged and how it's logged) can be separately defined as extensions of the abstraction and implementation. 该模式的一个有趣且有用的方面是,不同的独立特征(在此示例中,记录的内容及其记录方式)可以单独定义为抽象和实现的扩展。 This allows you to mix and match the characteristics without having a class structure that gets out of control. 这允许您混合和匹配特征,而不会失去控制的类结构。 The independence of these characteristics (ie orthogonality) will often require the methods in the two structures to be quite different. 这些特征(即正交性)的独立性通常要求两种结构中的方法完全不同。

  1. It has the structure of the Bridge pattern, in that it has the sort of class relationships and methods that are typical in the pattern. 它具有Bridge模式的结构,因为它具有模式中典型的类关系和方法。 I'm not sure that the semantics of your example are a good fit for this pattern. 我不确定你的例子的语义是否适合这种模式。 The main gist of this pattern is that you have a class that uses one or more implementation classes. 这种模式的主要要点是你有一个使用一个或多个实现类的类。 Would you say your Animal classes provide the implementation for Environment ? 你会说你的Animal类为Environment提供实现吗?

  2. Yes, you can indeed use abstract classes. 是的,你确实可以使用抽象类。 Remember, design patterns are typical language-agnostic. 请记住,设计模式是典型的语言无关。 In some languages, such as C++, interfaces are created using classes that contain pure abstract methods, since unlike Java there is no specific keyword for an interface in C++. 在某些语言(如C ++)中,接口是使用包含纯抽象方法的类创建的,因为与Java不同,C ++中的接口没有特定的关键字。 The label "interface" in diagrams denotes an interface in the conceptual sense, not the actual Java keyword. 图中的标签“interface”表示概念意义上的接口,而不是实际的Java关键字。 In fact, you can even use a concrete class as your implementor, even though it's typically good practice to use an interface as that provides more flexibility. 实际上,您甚至可以使用具体类作为实现者,即使使用接口通常是一种很好的做法,因为它提供了更大的灵活性。

  3. No, it's not necessary to have methods that exactly mirror those of the implementor classes. 不,没有必要让方法完全反映实现者类的方法。 The implementor classes provide a number of implementation methods which are used by the other class. 实现者类提供了许多其他类使用的实现方法。 How it uses them depends on what features the class wants to provide. 它如何使用它们取决于该类想要提供的功能。

The Bridge pattern is more useful in other languages, such as C++, where it's known as the "pImpl idiom" or "opaque pointer", because it can be used to hide the implementation from users: they cannot see anything about the implementing class. Bridge模式在其他语言中更有用,例如C ++,它被称为“pImpl idiom”或“opaque pointer”,因为它可以用来隐藏用户的实现:他们看不到有关实现类的任何内容。 In Java, this kind of hiding is not possible. 在Java中,这种隐藏是不可能的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM