Pokazywanie postów oznaczonych etykietą factory. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą factory. Pokaż wszystkie posty

wtorek, 19 lutego 2013

[C#|Visual Studio] Threading: Tasks

Task to obiekt reprezentujący pewnną jednostkę pracy (fragment kodu), którą chcemy zrównoleglić. Korzysta on z puli wątków, co poprawia wydajność w stosunku do wątków uruchamianych przez klasę Thread. Głównym zadaniem Tasków jest optymalne wykorzystanie wielordzeniowości komputera, przy niskich kosztach pamięciowych zrównoleglania (możemy dodawać do puli wątków setki zadań, które zostaną wykonywane w najszybszy możliwy sposób). Co więcej wprowadzają kilka zupełnie nowych, bardzo ciekawych funkcjonalności, takich jak na przykład możliwość uruchamiania child - Tasków z poziomu danego Tasku.

Operacje poprzez Taski można wykonywać na kilka sposobów:

static void RunTasks()
{
    //1 delegate
    Task.Factory.StartNew(() => Console.WriteLine("Hello from a task!"));
    //2 Task<T> - return value
    Task<string> task = Task.Factory.StartNew<string>(() =>
    {
        using (var wc = new System.Net.WebClient())
            return wc.DownloadString("http://www.agh.edu.pl");
    });
    //3 constructor
    var task2 = new Task(() => Console.Write("Hello"));
    //wait for result
    Console.WriteLine(task.Result);
    task2.Start();
    //4 state object
    var task3 = Task.Factory.StartNew (Greet, "Hello");
    task3.Wait();  // Wait for task to complete.   
}

static void Greet (object state) { Console.Write (state); }

Startowanie child-Tasków:

Task parent = Task.Factory.StartNew(() =>
{
    Console.WriteLine("I am a parent");

    Task.Factory.StartNew(() =>
    {
        Console.WriteLine("I am detached");
    });

    Task.Factory.StartNew(() =>
    {
        Console.WriteLine("I am a child");
    }, TaskCreationOptions.AttachedToParent);
});

Dzięki opcji AttachedToParent, aby parent mógł zakończyć swoje zadanie, będzie musiał poczekać na wykonania childa z tą właśnie opcją.

Synchronizację z Taskami można wykonać na dwa sposoby: wywołując metodę Wait() z opcjonalnym timeoutem, lub pobierając wartość property Result. W obu przypadkach program musi zaczekać na zakończenie działania Tasków.

Wyjątki:

Wyjątki w kodzie Tasków są propagowane do wątku wywołującego taski i opakowane w specjalną klasę AggregateException.

static void ExceptionTest()
{
    int x = 0;
    Task<int> calc = Task.Factory.StartNew(() => 7 / x);
    try
    {
        Console.WriteLine(calc.Result);
    }
    catch (AggregateException aex)
    {
        Console.Write(aex.InnerException.Message);  // Attempted to divide by zero
    }
}

Wyjątki z child-Tasków propagowane są do parent Tasków.

Continuation

Metoda ContinueWith z klasy Task pozwala na wykonywanie podanego delegata po zakończeniu działania zadania.

Task task1 = Task.Factory.StartNew(() => Console.Write("antecedant.."));
Task task2 = task1.ContinueWith(ant => Console.Write("..continuation"));

Synchronizować można się także z wieloma Taskami stosując ContinueWithAll bądź ContinueWithAny.
 

sobota, 20 października 2012

[HTML|JS|CSS] JavaScript Patterns: Wzorce projektowe

Wzorce projektowe znane z języków obiektowych nie zawsze są łatwe do zaimplementowania w języku JavaScript. Aby uzyskać podobny efekt, często należy znać pewne specyficzne konstrukcje JS. Poniżej przedstawiono trzy wzorce przez tzw Gang of Four
. Ich implementacja w JS jest nieco inna od tej, którą wszyscy znają z języków obiektowych.

  • Singleton

Jeżeli chcemy zapewnić, aby pewien obiekt był zinstancjonowany tylko raz, można skorzystać z faktu, że funkcja jest obiektem, który może posiadać własne properties.

function MyObject(){

 if(typeof MyObject.instance !== "undefined"){
  return MyObject.instance;
 }

 this.name = "MyObject";
 this.counter = 0;

 MyObject.instance = this;
}

var o1 = new MyObject();
o1.counter++;
var o2 = new MyObject();
console.log(o2.counter);

Program wypisze 1. Problemem jest, że statyczna instancja jest publiczna, aby tego uniknąć można skorzystać z konstrukcji closure.

  • Factory

Wzorzec przydatny przy tworzeniu całych rodzin obiektów. Ma on na celu umożliwienie podjęcia decyzji o tym, który dokładnie obiekt ma zostać stworzony, podczas pracy programu. JavaScript ułatwia implementację wzorca, ponieważ warto pamiętać, że obiekty są parami typu klucz - wartość.

function VehicleMaker(){}

VehicleMaker.prototype.printType = function(){
 console.log(this.type);
};

VehicleMaker.factory = function(type){
 var constr = type,
  newvehicle;

 if(typeof VehicleMaker[constr] !== "function"){
  throw {
   name: "Error",
   message: constr + " not found"
  };
 }

 if(typeof VehicleMaker[constr].prototype.printType !== 
  "function"){
  VehicleMaker[constr].prototype = new VehicleMaker();  
 } 
 newvehicle = new VehicleMaker[constr]();
 return newvehicle;
};

VehicleMaker.Car = function(){
 this.type = 'car';
};

VehicleMaker.Bike = function(){
 this.type = 'bike';
};

VehicleMaker.Bus = function(){
 this.type = 'bus';
};

var bus = VehicleMaker.factory('Bus');
var car = VehicleMaker.factory('Car');
var bike = VehicleMaker.factory('Bike');

bus.printType();
car.printType();
bike.printType();

try{
 var whatever = VehicleMaker.factory('whatever');
}
catch(err){
 console.log(err);
}

  • Decorator

Wzorzec pozwala rozszerzać w pewien sposób jakiś obiekt w czasie pracy programu, bez z góry narzuconych reguł. Każdy obiekt po dekoracji zachowuje swoje właściwości plus dodatkowo dostaje coś ekstra. W przypadku języka JS do implementacji można wykorzystać listę dekoratorów i odpowiednią metodę, która wykona ich zadania gdy przyjdzie na to czas.

function Degree(name){
 this.name = name;
 this.decorators_list = [];
}

Degree.decorators = {};

Degree.decorators.Engineer = {
 getDegree: function(name){
  return "inz. " + name;
 }
};

Degree.decorators.Doctor = {
 getDegree: function(name){
  return "dr " + name;
 }
};

Degree.decorators.Professor = {
 getDegree: function(name){
  return "Prof. " + name;
 }
};

Degree.decorators.Print = {
 getDegree: function(name){
  console.log(name);
 }
};

Degree.prototype.decorate = function(decorator){
 this.decorators_list.push(decorator);
};

Degree.prototype.getDegree = function(){
 var fname = this.name,
  i,
  max = this.decorators_list.length,
  name;
 for(i = 0; i < max; i+=1){
  name = this.decorators_list[i];
  fname = Degree.decorators[name].getDegree(fname); 
 }
 return fname;
};

var prof = new Degree("Jan Kowalski");
prof.decorate('Engineer');
prof.decorate('Doctor');
prof.decorate('Professor');
console.log(prof.getDegree());

niedziela, 7 października 2012

[HTML|JS|CSS] AngularJS: Services

Dzięki zastosowaniu serwisów AngularJS wspiera wzorzec projektowy Dependency Injection. Wzorzec ten znany z wielu obiektowych języków programowania ułatwia testowanie komponentów oraz podejmowanie decyzji o zależnościach w czasie pracy aplikacji. W przypadku Angulara podczas uruchomienia strony tworzony jest obiekt zwany injectorem, zarządzający wszystkimi serwisami. W momencie, gdy chcemy wykorzystać któryś z serwisów, injector zwraca jego instancję lub inicjuje go, jeśli nie nastąpiło to wcześniej. Ma tu więc miejsce połączenie wzorców singletonu oraz lazy-load. Samo wstrzykiwanie zależności można uzyskać na dwa sposoby: niejawnie podając nazwę serwisu jako argument funkcji (np. kontrolera), lub mechanizmem wstrzykiwania. Sposób pierwszy, choć czytelniejszy, napotyka jedną poważną przeszkodę. Podczas minifikacji i obfuskacji pliku ze skryptem zostają zmieniane nazwy zmiennych, również argumentów funkcji, przez co będziemy mieli do czynienia z zupełnie inną logiką. Drugi zapis, nieco dłuższy naprawia ten problem, kosztem czytelności kodu.
//DEPENDENCY INJECTION

function firstController($scope, $window){
 $scope.text = "firstController";
 $scope.introduce = function(e){
  $window.alert($scope.text);
 }
}

function secondController(s, w){
 s.text = "secondController";
 s.introduce = function(e){
  w.alert(s.text);
 }
}
secondController.$inject = ['$scope','$window'];

Mamy także możliwość tworzenia własnych serwisów dla naszych modułów. Dostarczając definicję, dostajemy w prezencie opisaną powyżej funkcjonalność, łącznie z możliwością wstrzykiwania naszego serwisu do kontrolera. Przykład poniżej.
angular.module('services', [], function($provide) {
    $provide.factory('mylogger', function() {
     var counter = 0;
     return function(text){
      counter += 1;
      console.log("Logging text number " + counter);
      console.log(text);
     }
    });
});

Przykład użycia w kontrolerze:
function firstController($scope, $window){
 $scope.text = "firstController";
 $scope.introduce = function(e){
  $window.alert($scope.text);
 }
}

Przez konwencję zaleca się, by nie nadawać własnym serwisom nazw rozpoczynających się od $, jako znaku zarezerwowanego dla serwisów Angulara.

wtorek, 10 lipca 2012

[Wzorce projektowe] Flyweight

Analogia z życia:

Chodząc do szkoły codziennie rano pakujemy do plecaka zeszyty. Mając pięć godzin lekcyjnych, w tym dwie godziny języka polskiego, zabierzemy cztery zeszyty (prawdopodobnie częściowo już zapisane). Moglibyśmy dla każdej lekcji każdego przedmiotu zakładać nowy zeszyt, ale byłoby to kosztowne zupełnie niepotrzebne. Każda nowa lekcja jest identyfikowana przez stronę, na której się znajduje i przez rodzaj zeszytu w jakim jest zapisana. Oczywiście do różnych przedmiotów mamy do dyspozycji różne zeszyty (w linie, kratkę, gładkie). Zawsze jednak jeden zeszyt może nam posłużyć do zapisywania lekcji przez cały semestr z danego przedmiotu.



Zastosowanie:

Wzorzec Flyweight znajduje zastosowanie wszędzie tam, gdzie mamy do czynienia z dużą ilością obiektów tego samego typu, co wiąże się z dużymi kosztami pamięciowymi przy przechowywaniu. Dzięki niemu możemy używać tego samego obiektu w wielu sytuacjach, przy zachowaniu całej elastyczności związanej z korzystaniem z niego, co powoduje, że zamiast używać np. setek instancji możemy skorzystać zaledwie z kilku. Aby było to możliwe, musimy wyciągnąć z obiektów ich zewnętrzny stan poza obiekt, przy zachowaniu wewnętrznych właściwości. Dzięki temu aplikacja nie zależy od tożsamości konkretnych instancji obiektów, mimo iż podchodząc w 100% obiektowo do modelowania zagadnienia musielibyśmy utworzyć o wiele więcej obiektów.

Zasada działania:

Na początku tworzymy pewien interfejs reprezentujący rodzinę obiektów. Następnie modelujemy różnice w obiektach poprzez konkretne implementacje tego interfejsu. W miejscu, w którym pojawia się zapotrzebowanie na obiekty posługujemy się fabryką, która zwraca już istniejące instancje i wywołuje na nich pewne akcje. Zewnętrzne cechy obiektów przekazywane są przez parametr.

Przykład implementacyjny:

  public interface ISoldier
    {
        int Damage { get; set; }
        void Shoot(int x, int y);
    }

    public class LightInfantry : ISoldier
    {
        public LightInfantry()
        {
            Damage = 20;
        }

        public int Damage { get; set; }

        public void Shoot(int x, int y)
        {
            Console.WriteLine(String.Format
                ("Shooting from ({0},{1}), done {2} damage",x,y,Damage));
        }
    }

    public class Artillery : ISoldier
    {
        public Artillery()
        {
            Damage = 200;
        }

        public int Damage { get; set; }

        public void Shoot(int x, int y)
        {
            Console.WriteLine(String.Format
                ("Shooting from ({0},{1}), done {2} damage", x, y, Damage));
        }
    }
public class SoldierFactory
    {
        private Dictionary<string, ISoldier> _instances =
            new Dictionary<string, ISoldier>();

        
        public ISoldier GetSoldier(string typeName)
        {
            switch (typeName)
            {
                case "LightInfantry":
                    if (!_instances.ContainsKey(typeName))
                        _instances.Add(typeName, new LightInfantry());
                    return _instances[typeName];
                case "Artillery" :
                    if (!_instances.ContainsKey(typeName))
                        _instances.Add(typeName, new Artillery());
                    return _instances[typeName];
                default:
                    throw new NotImplementedException();
            }
        }
    }
class Program
    {
        static void Main(string[] args)
        {
            CreateArmyAndAttack();
            Console.Read();
        }

        public static void CreateArmyAndAttack()
        {
            Random r = new Random();
            var factory = new SoldierFactory();
            for (int i = 0; i < 1000; i++)
            {
                factory.GetSoldier("LightInfantry")
                    .Shoot(r.Next() % 100, r.Next() % 100);
            }
            for (int i = 0; i < 100; i++)
            {
                factory.GetSoldier("Artillery")
                    .Shoot(r.Next() % 20, r.Next() % 100);
            }
        }
    }

piątek, 6 lipca 2012

[Wzorce projektowe] Simple Factory, Abstract Factory

Analogia z życia:

Automat do napojów wyrzuca puszki takich samych rozmiarów z napojami różnych producentów. Decyzja o tym, którą puszkę zwrócić podejmowana jest w momencie, gdy użytkownik naciśnie odpowiednie przyciski i wrzuci odpowiednie monety. Całym procesem przeliczania oraz wybrania żądanego napoju zajmuje się automat.




Zastosowanie:

Fabryk używamy, kiedy chcemy oddzielić proces tworzenia obiektu od podejmowania decyzji o tym, który obiekt chcemy utworzyć. Znacznie ułatwia to rozszerzanie możliwości podczas dalszego rozwoju oprogramowania. Fabryki bywają także użyteczne, gdy informacje o tym, który obiekt mamy utworzyć przechowywane są poza programem, na przykład w bazie danych, pliku .xml etc. Zatem warto stosować fabryki, gdy nie jesteśmy pewni, której konkretnej implementacji danego interfejsu będziemy w danym miejscu potrzebowali. Często w kodzie może się pojawić sporo wyrażeń typu if-else lub switch podczas tworzenia obiektów. Można je również zastąpić fabryką.

Simple Factory:

Pierwsza wersja fabryki ma za zadanie enkapsulację tworzenia obiektów. Decyzja o tym, który obiekt ma zostać zbudowany może zostać podjęta w czasie trwania programu np. na podstawie pliku konfiguracyjnego. Pobranie obiektu odbywa się za pomocą metody GetInstance z parametrem typu string, skojarzonym z typem przez dot Netowe Reflection.


public interface IDrink
    {
        string GetName();
    }

    public class CocaCola : IDrink
    {
        public string GetName()
        {
            return "Coca - Cola";
        }
    }

    public class Pepsi : IDrink
    {
        public string GetName()
        {
            return "Pepsi";
        }
    }

    public class Sprite : IDrink
    {
        public string GetName()
        {
            return "Sprite";
        }
    }
public class DrinkFactory
    {
        private Dictionary<string, Type> _drinks;

        public DrinkFactory()
        {
            LoadDrinks();
        }

        public void LoadDrinks()
        {
            _drinks = new Dictionary<string, Type>();
            var types = Assembly.GetExecutingAssembly().GetTypes();
            foreach (var type in types)
            {
                if(type.GetInterface(typeof(IDrink).ToString())!= null)
                {
                    _drinks.Add(type.Name,type);
                }
            }
        }

        public IDrink GetInstance(string typeName)
        {
            foreach (KeyValuePair<string, Type> pair in _drinks)
            {
                if (pair.Key.ToLower().Contains(typeName.ToLower()))
                    return Activator.CreateInstance(pair.Value) as IDrink;
            }
            throw new NotImplementedException();
        }
    }
 class Program
    {
        static void Main(string[] args)
        {
            var factory = new DrinkFactory();

            IDrink drink = factory.GetInstance("Cola");
            Console.WriteLine(drink.GetName());
            drink = factory.GetInstance("pepsi");
            Console.WriteLine(drink.GetName());
        }
    }

Abstract Factory :

Fabryka abstrakcyjna zapewnia jedynie interfejs do tworzenia rodzin powiązanych ze sobą pewien sposób obiektów. Konkretne fabryki, będące implementacjami fabryki abstrakcyjnej umożliwiają tworzenie całych rodzin obiektów w zależności od parametru. Jedna fabryka może tym razem tworzyć wiele obiektów za pomocą różnych metod. Sposób tworzenia obiektów wewnątrz konkretnej fabryki może być całkowicie dowolny.




    public interface ICar
    {
        Engine Engine { get; set; }
        string Name { get; set; }
    }

    public class VWGolf : ICar
    {
        public Engine Engine { get; set; }

        public string Name
        {
            get { return "Volkswagen Golf"; }
            set { throw new NotImplementedException(); }
        }
    }

    public class FordFocus : ICar
    {
        public Engine Engine { get; set; }

        public string Name
        {
            get { return "Ford Focus"; }
            set { throw new NotImplementedException(); }
        }
    }
 abstract public class Engine
    {
        public int Capacity { get; set; }
    }

    public class GasEngine : Engine
    {
        public GasEngine()
        {
            Capacity = 30;
        }
    }

    public class PetrolEngine : Engine
    {
        public PetrolEngine()
        {
            Capacity = 50;
        }

    }
    public abstract class CarAbstractFactory
    {
        public abstract ICar CreateAutoWithPetrolEngine();
        public abstract ICar CreateAutoWithGasEngine();
    }

    public class VWGolfFactory : CarAbstractFactory
    {
        private ICar BaseCreate()
        {
            return new VWGolf();
        }

        public override ICar CreateAutoWithPetrolEngine()
        {
            var car = BaseCreate();
            car.Engine = new PetrolEngine();
            return car;
        }

        public override ICar CreateAutoWithGasEngine()
        {
            var car = BaseCreate();
            car.Engine = new GasEngine();
            return car;
        }
    }

    public class FordFocusFactory : CarAbstractFactory
    {

        public override ICar CreateAutoWithPetrolEngine()
        {
            var car = new FordFocus();
            car.Engine = new PetrolEngine();
            return car;
        }

        public override ICar CreateAutoWithGasEngine()
        {
            var car = new FordFocus();
            car.Engine = new GasEngine();
            return car;
        }
    }
static void Main(string[] args)
        {
            CarAbstractFactory factory = LoadFactory();
            var car = factory.CreateAutoWithGasEngine();
            Console.WriteLine(car.Name);
            Console.WriteLine(car.Engine.Capacity);
        }

        public static CarAbstractFactory LoadFactory()
        {
            Random rnd = new Random();
            if (rnd.Next() % 2 == 0)
                return new VWGolfFactory();
            return new FordFocusFactory();
        }