如何为图像对象(BufferedImage、Image、ImageIcon)实现Java模板方法设计模式

4
以下是内容翻译:

如何为图像对象或不同类型的图像(例如:BufferedImageImageImageIcon)提供 template method design pattern 示例呢?我仅需要 Java 类中方法和它们的签名,以及字段,无需实际功能代码。基于不同类型的图像显示标题的机制相同,而显示图像的机制不同的事实。


3
你是在问是否需要一个展示该模式的新类,还是需要现有类的实例作为例子?你的问题目前表述不够清晰。此外,这个问题给人的感觉很像是“帮我开始写代码”,这在StackOverflow上不符合要求。 - jpmc26
3个回答

2

模板方法模式是一种行为设计模式,它在一个方法中定义了算法的程序框架。

Smalltalk的printString是一个模板方法。

我想Java中也有一个draw(Graphics g)方法,它也是一个模板方法。

在您的情况下,您可以在父类中拥有以下绘制模板方法。实现此方法的子类可以定义自己的算法来绘制图像。

public void draw(Image i);

例子

   class Image {
        int x1,y1,x2,y2; // may be boundaries of image common to all inherited 
objects
        String title;

        protected void displayTitle() {

        }
        // some code goes here
        public void draw() {
             // some code common to all image drawing
             // this might involve x and y declared above
             displayTitle();
             drawImage();
             // some more code after the template method
        }
        // the subclasses inheriting define their own algorithm to display image
        public abstract void drawImage();
    }

    class BufferedImage extends Image {
        // defines its own algorithm    
        public void drawImage() {
            // BufferedImage specific code to display the image
        }
    }

    class IconImage extends Image {
        // defines its own algorithm
        public void drawImage() {
            // IconImage specific code to display the image
        }
    }

    class DriverProgram {
        public static void main(String[] args) {
            Image[] image = {new BufferedImage(),new IconImage(),new XYXImage()};
            for(Image img:image) {
                img.draw();  // calling the template method
            }
        }
    }

如我所说,模板方法定义了一个算法的框架,其子类应该实现。它是非常优美的设计模式之一。


Java的toString()方法是一个模板方法。它并不定义任何算法框架。 - gontard
1
你的 Image::draw 实际上是一个模板方法。 - gontard
2
@gontard 你是对的,Java的toString()不是一个模板方法,我把它和Smalltalk的printString方法混淆了,后者才是一个模板方法。我已经编辑了我的答案以反映这一点。 - Prasad Shinde

1

理论:

模板方法模式允许你在超类的一个方法中定义算法的骨架,这个方法被称为模板方法

在这个模板方法内部,会调用一个或多个抽象方法来完成算法的一些步骤。这些抽象方法有时被称为占位符方法

由于它们是抽象的,在超类中没有实现。相反,它们由子类以不同的方式实现,因此在特定子类实例上调用继承的模板方法将使用它提供的占位符运行算法。

实现:

考虑使用泛型来实现更强大的模板模式,并将占位符方法定义为protected,因为它们只应该从模板方法内部调用。

如果您不想让子类覆盖模板方法,可以在抽象超类中将其声明为final

我假设你的示例中的BufferedImageImageIcon都是Image的子类,并且模板方法(算法)必须显示带有标题的图像:

// Class that defines the template method
// Generic parameter allows to define the specific type of image
// that will be handled by this image renderer
public abstract class ImageRenderer<T extends Image> {

    // This is the template method
    // It's final to avoid that subclasses override it
    public final void display(String title, T image) {
        // Display title
        this.displayTitle(title);
        // Let subclasses display specific type of image
        this.displayImage(image);
    }

    // Display title for every image type
    // This method is private since it's only called
    // from within the template method
    // (make it protected if you want to let subclasses 
    // override it, i.e. for custom title displaying)
    private void displayTitle(String title) {
        // Display title, no matter the image type
    }

    // Placeholder method, no implementation
    // Actual implementation is delegated to subclasses
    protected abstract void displayImage(T image);
}

BufferedImageRenderer类需要通过重写displayImage()方法来提供实现。这就是泛型的巨大帮助之处,因为displayImage()方法参数不需要进行向下转换(downcast)

public class BufferedImageRenderer 
    extends ImageRenderer<BufferedImage> {

    @Override
    protected void displayImage(BufferedImage image) {
        // Display specific buffered image
    }
}

同样的考虑也适用于 ImageIconRenderer 类:

public class ImageIconRenderer 
    extends ImageRenderer<ImageIcon> {

    @Override
    protected void displayImage(ImageIcon image) {
        // Display specific image icon
    }
}

那么,每当您需要显示特定图像及其标题时,只需创建适当的渲染器并调用模板方法,例如对于 ImageIcon

ImageIcon icon = getImageIconFromSomePlace();
String iconTitle = "My pretty icon";

ImageIconRenderer renderer = new ImageIconRenderer();
renderer.displayImage(iconTitle, icon);

感谢泛型,如果您尝试使用渲染器无法处理的图像调用displayImage(),将会产生编译错误。
BufferedImage bufferedImage = getBufferedImageFromSomePlace();
String bufferedImageTitle = "My amazing buffered image";

ImageIconRenderer renderer = new ImageIconRenderer();
renderer.displayImage(bufferedImageTitle, bufferedImage); // compilation error

0
在软件工程中,模板方法模式是一种行为设计模式,它在一个称为模板方法的方法中定义算法的程序骨架,并将某些步骤推迟到子类中。它允许重新定义算法的某些步骤而不改变算法的结构。
首先,您需要声明一个抽象类,该类将被其他图像类继承。它声明了一个抽象方法,该方法将由其他类实现,并且声明了一个将被实现此抽象类的类继承的方法:
public abstract class Template{    
    public String imageTitle;
    abstract public void displayImage(JLabel label); //abstract unimplemented method
    public void displayTitle(String imageTitle)
    {
        //Implement your display title method for all classes
    }       
}

然后,您可以定义您的类来实现抽象方法:

public class ImageIconClass extends Template{
    @Override
    public void displayImage(JLabel label) {
        // Implement specific display image method for ImageIconClass       
    }
}

public class ImageClass extends Template{
    @Override
    public void displayImage(JLabel label) {
         // Implement specific display image method for ImageClass          
    }
}

public class BufferedImageClass extends Template{
     @Override
    public void displayImage(JLabel label) {
       // Implement specific display image method for BufferedImageClass        
    }    
}

JLabel 用于显示图像。


1
模板方法在哪里? - fps
2
根据我的看法,这不是一个模板方法。displayImage()和displayTitle()都不是模板。 - Prasad Shinde
@Prasad Shinde,你能解释一下你的想法吗?你所说的“displayImage()和displayTitle()都不是模板”是什么意思?模板方法设计模式由诸如从超类继承属性的类之类的实体组成。在这种情况下,超类可以有一个或多个抽象方法(displayImage),这些方法旨在由继承超类的类来实现。超类还具有方法(displayTitle),这些方法对于扩展超类的所有类都是通用的。这就是模板方法的基础。基本上,模板方法是一个包装器类。 - Dn24Z

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接