Creational patterns

** Abstract Factory

Tips: Use when got different modules have the same type of component with a different implementation. The factory method also got an abstracted interface for adapting different factory implementation.

package main
import (
	"fmt"
	"errors"
)

type  iWeaponFacotry interface {
	makeGun() iGun
	makeBullet() iBullet
}

// gun
type iGun interface {
	setName(name string)
	getName() string
}
type gun struct {
	name string
}
func (g *gun) setName(name string) {
	g.name = name
}
func (g *gun) getName() string {
	return g.name
}

//bullet
type iBullet interface {
	setType(typeS string)
	getType() string
}

type bullet struct {
	typeS string
}

func (b *bullet) setType(typeS string) {
	b.typeS = typeS
}

func (b *bullet) getType() string {
	return b.typeS
}


// implementFactory for CompanyA 


type CompanyA struct{
}

type CompanyAGun struct {
	gun
}

type CompanyABullet struct {
	bullet
}
func (c *CompanyA) makeGun() iGun {
	return &CompanyAGun{
		gun: gun{
			name: "AK47",
		},
	}
}

func (c *CompanyA) makeBullet()  iBullet {
	return &CompanyABullet {
		bullet: bullet{
			typeS:"7mm",
		},
	}
}


func getFactory(company string) (iWeaponFacotry, error) {
	if(company == "CompanyA") {
		return &CompanyA{}, nil
	}
	return nil, errors.New("Invalid company")
}


func main() {
	compangAFactory, err := getFactory("CompanyA")
	if err != nil {
		panic(err)
	}
	companyAGun := compangAFactory.makeGun()
	companyABullet := compangAFactory.makeBullet()

	fmt.Println(companyAGun.getName(), companyABullet.getType())
}