Метод Фабрика (шаблон)

от Уикипедия, свободната енциклопедия
UML диаграма на Метод Фабрика

Метод Фабрика е създаващ шаблон за дизайн, който се използва в обектно-ориентираното програмиране.

Фабриката има за цел инстанцирането на различни обекти, чиито типове не са предефинирани. Обектите се създават динамично в зависимост от параметрите предадени на фабриката. По принцип фабриките са единствени в дадена програма, затова за създаването им често се използва шаблонът Сек (Singleton).

Примери[редактиране | редактиране на кода]

C++[редактиране | редактиране на кода]

#include<iostream>
#include<string>
using namespace std;

// "Product"
class Product{
public:
	virtual string getName() = 0;
};

// "ConcreteProductA"
class ConcreteProductA: public Product{
public:
	string getName(){
		return "ConcreteProductA";
	}
};

// "ConcreteProductB"
class ConcreteProductB: public Product{
public:
	string getName(){
		return "ConcreteProductB";
	}
};

// "Creator"
class Creator{
public:
	virtual Product* FactoryMethod() = 0;
};

// "ConcreteCreatorA"
class ConcreteCreatorA: public Creator{
public:
	Product* FactoryMethod() {
		return new ConcreteProductA();
	}
};

// "ConcreteCreatorB"
class ConcreteCreatorB: public Creator{
public:
	Product* FactoryMethod() {
		return new ConcreteProductB();
	}
};

int main(){
	const int size = 2;
	// An array of creators
	Creator* creators[size];
      creators[0] = new ConcreteCreatorA();
      creators[1] = new ConcreteCreatorB();

	// Iterate over creators and create products
	for(int i=0;i<size;i++){
		Product* product = creators[i]->FactoryMethod();
		cout<<product->getName()<<endl;
		delete product;
	}

	int a;
	cin>>a;

	for(int i=0;i<size;i++){
		delete creators[i];
	}
	return 0;
}

C#[редактиране | редактиране на кода]

 // Factory Method pattern -- Structural example

  class MainApp
  {
    static void Main()
    {
      // An array of creators
      Creator[] creators = new Creator[2];
      creators[0] = new ConcreteCreatorA();
      creators[1] = new ConcreteCreatorB();

      // Iterate over creators and create products
      foreach(Creator creator in creators)
      {
        Product product = creator.FactoryMethod();
        Console.WriteLine("Created {0}",
          product.GetType().Name);
      }

      // Wait for user
      Console.Read();
    }
  }

  // "Product"

  abstract class Product
  {
  }

  // "ConcreteProductA"

  class ConcreteProductA: Product
  {
  }

  // "ConcreteProductB"

  class ConcreteProductB: Product
  {
  }

  // "Creator"

  abstract class Creator
  {
    public abstract Product FactoryMethod();
  }

  // "ConcreteCreatorA"

  class ConcreteCreatorA: Creator
  {
    public override Product FactoryMethod()
    {
      return new ConcreteProductA();
    }
  }

  // "ConcreteCreatorB"

  class ConcreteCreatorB: Creator
  {
    public override Product FactoryMethod()
    {
      return new ConcreteProductB();
    }
  }

Java[редактиране | редактиране на кода]

abstract class Pizza {
    public abstract double getPrice();
}

class HamAndMushroomPizza extends Pizza {
    private double price = 8.5;

    public double getPrice() {
        return price;
    }
}

class DeluxePizza extends Pizza {
    private double price = 10.5;

    public double getPrice() {
        return price;
    }
}

class HawaiianPizza extends Pizza {
    private double price = 11.5;

    public double getPrice() {
        return price;
    }
}

class PizzaFactory {
    public enum PizzaType {
        HamMushroom,
        Deluxe,
        Hawaiian
    }

    public static Pizza createPizza(PizzaType pizzaType) {
        switch (pizzaType) {
            case HamMushroom:
                return new HamAndMushroomPizza();
            case Deluxe:
                return new DeluxePizza();
            case Hawaiian:
                return new HawaiianPizza();
        }
        throw new IllegalArgumentException("The pizza type " + pizzaType + " is not recognized.");
    }
}

class PizzaLover {
    /**
     * Create all available pizzas and print their prices
     */
    public static void main (String args[]) {
        for (PizzaFactory.PizzaType pizzaType: PizzaFactory.PizzaType.values()) {
            System.out.println("Price of " + pizzaType + " is " + PizzaFactory.createPizza(pizzaType).getPrice());
        }
    }
}
 public class FactoryMethodExample
 {
     public static void main(String[] args)
     {
         // an array of creators
         Creator[] creators = new Creator[2];
         creators[0] = new ConcreteCreatorA();
         creators[1] = new ConcreteCreatorB();

         // iterate over creators and create products
         for (Creator creator: creators)
         {
             Product product = creator.factoryMethod();
             System.out.printf("Created {%s}\n", product.getClass());
         }
     }
 }

 // Product
 abstract class Product
 {
 }

 // ConcreteProductA
 class ConcreteProductA extends Product
 {
 }

 // ConcreteProductB
 class ConcreteProductB extends Product
 {
 }

 // Creator
 abstract class Creator
 {
     public abstract Product factoryMethod();
 }

 // Този клас може да има неопределен брой наследници.
 // За създаването на нужните ни обекти можем да напишем следните фабрики: ConcreteCreatorA, ConcreteCreatorB

 // ConcreteCreatorA
 class ConcreteCreatorA extends Creator
 {
     @Override
     public Product factoryMethod()
     {
         return new ConcreteProductA();
     }
 }

 // ConcreteCreatorB
 class ConcreteCreatorB extends Creator
 {
     @Override
     public Product factoryMethod()
     {
         return new ConcreteProductB();
     }
 }

 //Резултат:
 //Created {class ConcreteProductA}
 //Created {class ConcreteProductB}

Perl[редактиране | редактиране на кода]

START ===== D:\etl\Perl\DesignPatterns\RunFactoryDesignPattern.cmd
perl -w "D:\etl\Perl\DesignPatterns\RunFactoryDesignPattern.pl"

pause
END ================== D:\etl\Perl\DesignPatterns\RunFactoryDesignPattern.cmd

.
START ===== D:\etl\Perl\DesignPatterns\RunFactoryDesignPattern.pl
   use strict; use warnings;

    use GreetFactory;

    my $greeter_n = GreetFactory->instantiate("Repeat", "I am repeating Hello x amount of times \n", 3);
    $greeter_n->greet();

    my $greeter_stamp = GreetFactory->instantiate("Stamp", "The Stamp says Good-bye\n");
    $greeter_stamp->greet();
END ================== D:\etl\Perl\DesignPatterns\RunFactoryDesignPattern.pl

.
START ===== D:\etl\Perl\DesignPatterns\GreetFactory.pm
package GreetFactory;
use strict; use warnings;

# ARHH NO TIME HARDCODING ...
BEGIN{ push @INC, 'D:/etl/Perl/DesignPatterns'; }

    sub instantiate {
				my $class = shift;
				my $requested_type = shift;
				my $location = "Greet/$requested_type.pm";
				my $class = "Greet::$requested_type";

        require $location;

        return $class->new(@_);
    }

    1;
END ================== D:\etl\Perl\DesignPatterns\GreetFactory.pm

.
START ===== D:\etl\Perl\DesignPatterns\Greet\Repeat.pm
package Greet::Repeat;

sub new {
    my $class    = shift;
    my $self     = {
        greeting => shift,
        repeat   => shift,
    };
    return bless $self, $class;
}

sub greet {
    my $self = shift;
    print ($self->{greeting} x $self->{repeat});
}

1;
END ================== D:\etl\Perl\DesignPatterns\Greet\Repeat.pm

.
START ===== D:\etl\Perl\DesignPatterns\Greet\Stamp.pm
package Greet::Stamp;
use strict; use warnings;

sub new {
				my $class = shift;
				my $greeting = shift;
				return bless \$greeting, $class;
}

sub greet {
				my $greeting = shift;
				my $stamp = timestamp();
				print "$stamp $$greeting";
}

sub timestamp {
 #
 # Purpose: returns the time in yyyymmdd-format
 #
 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
 #---- change 'month'- and 'year'-values to correct format ----
 $min = "0$min" if ($min < 10);
 $hour = "0$hour" if ($hour < 10);
 $mon = $mon + 1;
 $mon = "0$mon" if ($mon < 10);
 $year = $year + 1900;
 $mday = "0$mday" if ($mday < 10);
 return "$year$mon$mday" . "_" . "$hour$min" . "_" . $sec;
}

1;
END ================== D:\etl\Perl\DesignPatterns\Greet\Stamp.pm