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

时间:2016-11-02 09:56:32

标签: java bridge

我正在努力提高我对设计模式的了解,而且我对Bridge模式有点困惑。您可以在下面看到我的示例:

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();
    }
}

我的问题:

  1. 这是一个正确的桥模式吗?
  2. 如果接口被替换,是否可以使用Bridge模式 抽象类(我在这个tutoarial中看到了这种方法 http://www.newthinktank.com/2012/10/bridge-design-pattern-tutorial/)。 但根据这个 (https://dzone.com/articles/design-patterns-bridge)似乎是 在我的情况下,动物不应该是一个抽象的类..
  3. 是否有必要使用方法someAnimalEats()和 Environment类中的someAnimalMoves()?更准确地说,是吧 强制要在这个类中对应每个方法 Animal界面的方法?
  4. 非常感谢!

2 个答案:

答案 0 :(得分:5)

  1. 您展示的域名(动物及其环境)对于桥梁模式来说并不是一个很好的用例。它有一个非常特定的目的:将抽象(包括该抽象的扩展)与实现(可能还包括扩展)分开。其中一个关键特征是抽象引用了实现(名称中的桥接器),而不是实现扩展或实现抽象的实现。通常,具体实现由客户端在运行时决定。
  2. 对于模拟现实世界物体(如动物和环境)的桥梁的自然用例并不容易。更容易想到旨在执行某些功能的类。

    // 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 ...
    

    客户端可能会执行以下操作:

    Logger logger = new ErrorLogger(new FileLogOutputter("errors.log"));
    
    1. 我建议我在这个例子中使用的类/接口组合是相当典型的。你可以创建抽象和接口,但考虑到桥接点是引用实现它使它更容易使它成为一个抽象类。

    2. 希望这个例子也回答这个问题:你可以在抽象和实现中使用类似的方法,但它当然不是必需的。该模式的一个有趣且有用的方面是,可以将不同的独立特征(在此示例中,记录的内容以及它的记录方式)分别定义为抽象和实现的扩展。这允许您混合和匹配特征,而不会失去控制的类结构。这些特征(即正交性)的独立性通常要求两种结构中的方法完全不同。

答案 1 :(得分:2)

  1. 它具有Bridge模式的结构,因为它具有模式中典型的类关系和方法。我不确定你的例子的语义是否适合这种模式。这种模式的主要要点是你有一个使用一个或多个实现类的类。您是否说Animal课程为Environment提供了实施?

  2. 是的,你确实可以使用抽象类。请记住,设计模式是典型的语言无关。在某些语言(如C ++)中,接口是使用包含纯抽象方法的类创建的,因为与Java不同,C ++中的接口没有特定的关键字。图中的标签“interface”表示概念意义上的接口,而不是实际的Java关键字。实际上,您甚至可以使用具体类作为实现者,即使使用接口通常是一种很好的做法,因为它提供了更大的灵活性。

  3. 不,没有必要让方法与实现者类的方法完全相同。实现者类提供了许多其他类使用的实现方法。它如何使用取决于该类想要提供的功能。

  4. Bridge模式在其他语言中更有用,例如C ++,它被称为“pImpl idiom”或“opaque pointer”,因为它可以用来隐藏用户的实现:他们看不到任何关于实施课程。在Java中,这种隐藏是不可能的。