# Golang - Template Method Pattern

The Template Method Pattern is a behavioral design pattern that defines the skeleton of an algorithm in a superclass but lets subclasses override specific steps of the algorithm without changing its structure. In other words, the Template Method Pattern provides a template for performing an operation but allows the subclasses to modify certain steps of the operation without changing its overall structure.

The Template Method Pattern is a part of the "Gang of Four" design patterns, which were first introduced in their book "Design Patterns: Elements of Reusable Object-Oriented Software". The "Gang of Four" includes Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. These patterns are widely used in software development to solve commonly occurring problems in object-oriented programming.

# Example

Let's consider a real-world example of how the Template Method Pattern can be used in Golang programming. Suppose we want to create a program that reads data from different sources and then processes it. The sources can be files, databases, or even remote APIs. We can create an abstract class that defines the template for reading and processing data.

```go
type DataReaderProcessor interface {
    ReadData() ([]byte, error)
    ProcessData(data []byte) error
    GetDataSourceName() string
}

type DataReaderProcessorTemplate struct {
    dataSource DataReaderProcessor
}

func (p *DataReaderProcessorTemplate) ReadAndProcessData() error {
    data, err := p.dataSource.ReadData()
    if err != nil {
        return err
    }
    err = p.dataSource.ProcessData(data)
    if err != nil {
        return err
    }
    return nil
}

func (p *DataReaderProcessorTemplate) GetDataSourceName() string {
    return p.dataSource.GetDataSourceName()
}

```

In the above code, we have defined an interface `DataReaderProcessor` that specifies the methods required for reading and processing data. We then define a `DataReaderProcessorTemplate` struct that implements the `DataReaderProcessor` interface. The `DataReaderProcessorTemplate` struct provides a template for reading and processing data.

The `ReadAndProcessData` method reads data from the data source and processes it by calling the `ProcessData` method. The `GetDataSourceName` method returns the name of the data source.

Now we can create structs that implement the `DataReaderProcessor` interface and implement the `ReadData` and `ProcessData` methods according to their specific data sources. For example, we can define a `FileReaderProcessor` that reads data from a file and a `DatabaseReaderProcessor` that reads data from a database.

```go
type FileReaderProcessor struct {
    DataReaderProcessorTemplate
    fileName string
}

func (p *FileReaderProcessor) ReadData() ([]byte, error) {
    data, err := ioutil.ReadFile(p.fileName)
    if err != nil {
        return nil, err
    }
    return data, nil
}

func (p *FileReaderProcessor) ProcessData(data []byte) error {
    // process data
    return nil
}

func (p *FileReaderProcessor) GetDataSourceName() string {
    return p.fileName
}

type DatabaseReaderProcessor struct {
    DataReaderProcessorTemplate
    db *sql.DB
}

func (p *DatabaseReaderProcessor) ReadData() ([]byte, error) {
    // read data from database
    return nil, nil
}

func (p *DatabaseReaderProcessor) ProcessData(data []byte) error {
    // process data
    return nil
}

func (p *DatabaseReaderProcessor) GetDataSourceName() string {
    return "Database"
}

```

In the above code, we have defined `FileReaderProcessor` and `DatabaseReaderProcessor` structs that implement the `DataReaderProcessor` interface. These classes implement the `ReadData` and `ProcessData` methods according to their data sources.

Now we can use these structs to read and process data from different sources. For example, we can create a `FileReaderProcessor` object and call its `ReadAndProcessData` method to read and process data from a file.

```go
func main() {
    processor := &FileReaderProcessor{
        DataReaderProcessorTemplate: DataReaderProcessorTemplate{
            dataSource: &FileReaderProcessor{
                fileName: "/path/to/file",
            },
        },
    }
    err := processor.ReadAndProcessData()
    if err != nil {
        log.Fatalf("Error: %v", err)
    }
}

```

In the above code, we have created a `FileReaderProcessor` object and passed it to the `DataReaderProcessorTemplate` struct. We then call the `ReadAndProcessData` method to read and process data from the file.

# Conclusion

The Template Method Pattern provides a way to define the skeleton of an algorithm in a superclass but allows subclasses to modify specific steps of the algorithm without changing its overall structure. This pattern is useful in situations where we want to define a common algorithm but allow subclasses to customize certain steps of the algorithm. In Golang, we can use the Template Method Pattern to create a template for reading and processing data from different sources. The pattern allows us to define a common algorithm for reading and processing data but allows subclasses to customize the specific data source.

---

# References

* [**“Design Patterns: Elements of Reusable Object-Oriented Software**](https://amzn.to/3SJenIZ)” by Erich Gamma, John Vlissides, Ralph Johnson, and Richard Helm
