Method Chaining pattern

Method Chaining là một kỹ thuật lập trình đơn giản có thể được cài đặt trên hầu hết các ngôn ngữ lập trình hướng đối tượng. Tư tưởng của phương pháp này là: trong một method, làm gì đó với đối tượng hiện tại “this” và return chính “this”. Và vì method trả về “this”, nên khi ấy chúng ta có thể gọi tiếp một method khác của đối tượng này bằng cách viết code nối vào sau, trên cùng một dòng, khá tiện lợi và nhanh gọn, nhất là khi các IDE ngày nay đều có tính năng autocomplete rất mạnh.

Sẽ dễ hiểu hơn khi xem ví dụ này, xây dựng một lớp hình chữ nhật với các phương thức Setter:

class ChainedRectangle
{
    protected int x;
    public ChainedRectangle setX(int x)
    {
        this.x = x; return this;
    }

    protected int y;
    public ChainedRectangle setY(int y)
    {
        this.y = y; return this;
    }

    protected int width;
    public ChainedRectangle setWidth(int width)
    {
        this.width = width; return this;
    }

    protected int height;
    public ChainedRectangle setHeight(int height)
    {
        this.height = height; return this;
    }

    protected String color;
    public ChainedRectangle setColor(String color)
    {
        this.color = color; return this;
    }
}

Lúc này để tạo ra một hình chữ nhật với các kích thước mong muốn ta chỉ cần viết:

new Rectangle().setX(10).setY(10).setWidth(13)
        .setHeight(15).setColor("red");

Một ví dụ khác cũng cho thấy sự tiện lợi của phương pháp này: truy vấn (Query) trong database.

public class Query
{
    protected String queryString = "";

    public Query select(String what)
    {
        queryString = "SELECT " + what;
    }

    public Query from(String from)
    {
        queryString += " FROM " + from;
    }

    public Query where(String where)
    {
        queryString += " WHERE " + where;
    }

    public ResultSet Invoke()
    {
        //... database invocation bla bla
        return result;
    }
}

Và truy vấn rất dễ dàng:

new Query().select("*").from("table").where("a=b").Invoke();

Vấn đề của Method Chaining là ta khó có thể đảm bảo thứ tự gọi các method cho hợp lý. Rõ ràng trong nhiều trường hợp, ta muốn khi 1 method được gọi xong, thì sau đó chỉ được gọi 1 trong các method giới hạn nào đó; hoặc là có 1 method nào đó muốn gọi phải gọi trước nó 1 method khác. Như trong ví dụ trên, sau mệnh đề SELECT ta chỉ muốn gọi WHERE, và sau WHERE ta chỉ muốn gọi FROM. Và tất nhiên, để làm điều này có thể thiết kế dùng Interface, kiểu trả về của method là 1 Interface mà trong Interface đó ta chỉ giới hạn 1 số method cho phép. Lớp hiện tại implements Interface này nên “return this” vẫn hợp lệ.

public interface ISelectedQuery
{
    IFromQuery from(String from);
}

public interface IFromQuery
{
    Query where(String where);
}

public class Query implements ISelectedQuery, IFromQuery
{
    protected String queryString = "";

    public ISelectedQuery select(String what)
    {
        queryString = "SELECT " + what;
        return this;
    }

    public IFromQuery from(String from)
    {
        queryString += " FROM " + from;
        return this;
    }

    public Query where(String where)
    {
        queryString += " WHERE " + where;
        return this;
    }

    public ResultSet Invoke()
    {
        //... database invocation bla bla
        return result;
    }
}
Advertisements

3 thoughts on “Method Chaining pattern

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s