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

wtorek, 3 listopada 2015

[HTML|JS|CSS] ES6: Classes

Nowa specyfikacja EcmaScript wproawdza słowo kluczowe class, by znacznie uprościć budowanie obiektowych konstrukcji w JS. Do tej pory obiekty tworzyliśmy między innymi za pomocą konstruktorów (funkcja wołana ze słowem kluczowym new), natomiast za dziedziczenie odpowiadało property prototype. ES6 wprowdza klasy, aby uporządkować te mechanizmy. Jedynym celem, dla którego powinniśmy używać klas jest tworzenie obiektów.

Klasy możemy definiować na dwa sposoby:

// class declaration
class Car
{
  constructor(make)
  {
    this.make = make;
  }
}

var ford = new Car("Ford");
console.log(ford.make);

console.log(typeof Car); //function

// class expression syntax
var Plane = class {
  constructor(make)
  {
    this.make = make;
  }
}

var plane = new Plane("Airbus");
console.log(plane.make);

Poza konstruktorami, klasy mogą zawierać regularne funkcja (które zostaną dodane do prototypu obiektu), oraz settery i gettery pozwalające na zaimplementowanie reguł enkapsulacji (jak na przykład w C#). Specjalnym rodzajem metod są metody statyczne - nie zostaną one dodane do prototype, tylko do samej klasy.

class Tank
{
  constructor()
  {
    this._name = "";
  }

  get name(){
  	console.log("getting name");
  	return this._name;
  }

  set name(value){
  	console.log("setting name");
  	this._name = value;
  }

  fire(){
  	console.log("fire !");
  }

  static report(){
  	console.log("reporting !");
  }
}


var abrams = new Tank();
abrams.name = "Abrams";
console.log(abrams.name);
abrams.fire();
Tank.report();

console.log(typeof abrams.__proto__.fire); //function
console.log(typeof abrams.__proto__.report); //undefined

Klasy niosą za sobą także możliwość dziedziczenia, reprezentowaną przez słowo kluczowe extends. Dziedziczyć można po klasie lub bezpośrednio po konstruktorze. Drugie, nowe słowo kluczowe to super. Służy ono do wywołania konstruktora bazowego oraz do odwołania się do metod z bazowego konstruktora.

function A(a)
{
  this.a = a;
}

A.prototype.printA = function(){
  console.log(this.a);
}

class B extends A
{
  constructor(a, b)
  {
    super(a);
    this.b = b;
  }

  printB()
  {
    console.log(this.b);
  }

  static sayHello()
  {
    console.log("Hello");
  }
}

class C extends B
{
  constructor(a, b, c)
  {
    super(a, b);
    this.c = c;
  }

  printC()
  {
    console.log(this.c);
  }

  printAll()
  {
    this.printC();
    super.printB();
    super.printA();
  }
}

var obj = new C(1, 2, 3);
obj.printAll();

C.sayHello();
asdasd

czwartek, 18 października 2012

[HTML|JS|CSS] JavaScript Patterns: Tworzenie obiektów

Tym razem kilka wzorców projektowych charakterystycznych dla języka JavaScript, które przydają się przy tworzeniu obiektów. Z jakimi podstawowymi problemami spotyka się programista w tym języku ? Przede wszystkim jest to brak klas i przestrzeni nazw. Poniżej użyteczne wzorce.

  • Przestrzeń nazw

Spore zapotrzebowanie na zmienne globalne powoduje zaśmiecanie obiektu okna. Aby temu zapobiec tworzy się jeden globalny obiekt będący odpowiednikiem modułu reprezentującego pewne właściwości.

var mymodule = mymodule || {};
mymodule.length = 3;
mymodule.maxusers = 15;
mymodule.config = {};
mymodule.config.initialtext = "hello world";

  • Prywatne składowe

Aby uzyskać efekt prywatnych składowych obiektu można skorzystać z konstrukcji closure.

function Person(name){
 var myname = name;
 this.getName = function(){
  return myname;
 };
 this.setName = function(str){
  myname = str;
 };
}

var sb = new Person("John");
console.log(sb.myname);
console.log(sb.getName());
sb.setName("Joe");
console.log(sb.getName());

  • Wzorzec modułu

Połączenie kilku mniejszych wzorców, mające na celu utworzenie obiektu będącego modułem z prywatnymi zmiennymi, metodami itd.

var mymodule = {};
mymodule.array = {};
mymodule.array.utils = function(){
 //private members
 var logged = 0;
 var logger = function(i,e){
  logged++;
  console.log("Index:" + i + ", element: " + e);
 };
 //public members
 var totalLogged = function(){
  return logged;
 };
 var printArray = function(array){
  for (var i = array.length - 1; i >= 0; i--) {
   logger(i,array[i]);
  }
 };
 //public API
 return{
  print : printArray,
  total : totalLogged
 };
}();

var myarray = ['one','two','three'];

mymodule.array.utils.print(myarray);
console.log(mymodule.array.utils.total());

  • Sandbox

Ulepszona wersja wzorca przestrzeni nazw. Ponieważ każda funkcja jest obiektem, możemy w niej enkapsulować serwisy i przez samą funkcję się do nich odwoływać oraz zwracać je za pomocą callbacku.

function Sandbox(){
 var args = Array.prototype.slice.call(arguments),
 callback = args.pop(),
 modules = (args[0] && typeof args[0] === "string") ? args : args[0],
 i;

 if(! (this instanceof Sandbox)){
  return new Sandbox(modules, callback);
 }

 for(i = 0; i < modules.length; i += 1){
  Sandbox.modules[modules[i]](this);
 }

 return callback(this);
}

Sandbox.modules = {};
Sandbox.modules.vector = function(box) {
 box.sum = function(v){
  var sum = 0;
  for (var i = v.length - 1; i >= 0; i--) {
   sum += v[i];
  }
  return sum;
 };
 box.normalize = function(v,sumfun){
  var sum = sumfun(v);
  var arr = [];
  for (var i = v.length - 1; i >= 0; i--) {
   arr.push(v[i]/sum);
  }
  console.log(arr);
 };
};

Sandbox('vector', function(box){
 var a = [1,2,3,4];
 console.dir(box.sum(a));
 box.normalize(a,box.sum);
});

  • Statyczne pola

Aby uzyskać konstrukcję składniową statycznego pola, znaną z języków obiektowych typu C++, należy pamiętać o tym, że każda funkcja jest obiektem, do którego można dynamicznie przypisywać właściwości.

function Computer(){
 Computer.instances++;
 return {
  ram : 4096,
  hdd : 1024
 };
}

Computer.instances = 0;

var computers = [new Computer(), new Computer()];
console.log(Computer.instances);

  • Chaining pattern


Jest to wzorzec umożliwiający wywoływanie wielu funkcji w łańcuchu, co poprawia czytelność kodu i zmniejsza jego ilość, kosztem utrudnień w testowaniu.
var number = {
 value : 0,
 add : function(x){
  this.value += x;
  return this;
 },
 multiply : function(x){
  this.value *= x;
  return this;
 },
 print : function(){
  return this.value;
 }
};

console.log(number.add(10).multiply(12).print());

czwartek, 11 października 2012

[HTML|JS|CSS] Node.js: RESTful API

Aby serwer mógł komunikować się ze stroną, możemy w prosty sposób wystawić RESTowe API dostosowane do naszych potrzeb. Z użyciem Node.js oraz expressa staje się to bardzo proste. Mamy do dyspozycji cztery metody:
  • GET
  • POST
  • PUT
  • DELETE
Poniżej przykład, jak zaprojektować takie API po stronie serwerowej. Użyto w nim dwóch obiektów middleware. Obiekt express.bodyParser, jak nazwa wskazuje parsuje body requestów typu post na obiekt javascript, dzięki czemu można odwoływać się do poszczególnych propercji takiego obiektu. Użycie express.static konfiguruje ścieżkę do szablonu html względem pliku serwera.

var express = require('express');
var app = express();

app.use(express.bodyParser());
app.use(express.static(__dirname + '/www'));

Samo API można zaprojektować w taki sposób jak poniżej.

app.get('/store/:key', function(req, resp) {
 var val = store[req.params.key];
 if(val){
  resp.send(val);
 }
 else{
  resp.send('undefined',400);
 }
});

app.post('/store/', function(req, resp) {
 store[req.body.key] = req.body.value;
    resp.send('OK');
});

app.put('/store/', function(req, resp){
 store[req.body.key] = req.body.value;
    resp.send('OK');
});

app.del('/store/:key', function(req, resp) {
 var val = store[req.params.key];
 console.log(req.params.key);
 if(val){
  store[req.params.key] = undefined;
  resp.send("OK");
 }
 else{
  resp.send('undefined',400);
 }
});

czwartek, 23 sierpnia 2012

[WPF] Logical Resources

Zasobem logicznym może być np. kolor, brush czy czcionka. Mamy do dyspozycji dwa rodzaje zasobów logicznych.

StaticResource -statyczne, ładowane w momencie uruchamiania aplikacji, nie podlegają zmianom w czasie trwania aplikacji, ale też nie wymagają dodatkowych zasobów do śledzenia zmian.

DynamicResource - mogą być zmieniane wielokrotnie w czasie trwania aplikacji, ładowane są dopiero w momencie, kiedy zachodzi taka potrzeba, np. przy wejściu do danej strony.

Na poziomie okna zasoby definiowane są w następujący sposób :

    <Window.Resources>
        <SolidColorBrush x:Key="myBrush" Color="Azure" />
    </Window.Resources>

Mogą być także definiowane na innych poziomach, np. w pliku App.xaml jako zasoby globalne dla całej aplikacji.

   <Application.Resources>
        <ResourceDictionary>
            <SolidColorBrush x:Key="globalBrush" Color="DarkOliveGreen" />
        </ResourceDictionary>
    </Application.Resources>

Do zasobów odwołujemy się w następujący sposób:

<Rectangle Fill="{StaticResource myBrush}" Name="rectangle1" Stroke="Black" VerticalAlignment="Top" Width="491" />
<Rectangle Fill="{DynamicResource globalBrush}"  Name="rectangle2" Stroke="Black" VerticalAlignment="Top" Width="491" />
   

Istnieje możliwość używania tych samych kluczy na różnych poziomach. Podczas wczytywania zasobu, przeszukiwane jest drzewo wizualne, od najbardziej lokalnego poziomu. Jeśli zostanie znaleziony zasób na poziomie okna, to jest on ładowany, jeśli nie, to sprawdzany jest poziom aplikacji, później zasoby systemowe, a gdy również tam nie zostanie nic znalezione, rzucany jest wyjątek.

Warto także pamiętać o tym, że domyślnie, gdy zdefiniujemy zasób i odwołamy się do niego w wielu miejscach, to używana jest jedna instancja. Możemy wymusić tworzenie nowego zasobu poprzez ustawiania atrybutu x:Shared=”False”.

Zasoby można także definiować oraz przydzielać z poziomu Code Behind.


 private void rectangle2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Resources.Add("addedResource", new SolidColorBrush(Colors.Khaki));
            App.Current.Resources.Add("newResource", new SolidColorBrush(Colors.Honeydew));
        }

        private void rectangle1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            ((Rectangle)sender).Fill = (SolidColorBrush)Resources["addedResource"];
            ((Rectangle)sender).Stroke = (SolidColorBrush)App.Current.Resources["newResource"];
        }

sobota, 28 lipca 2012

[Wzorce projektowe] Service Locator

Analogia z życia:

Dzisiejsze telefony komórkowe oferuję wiele funkcjonalności. Możemy na przykład napisać wiadomość tekstową lub do kogoś zadzwonić. Z punktu widzenia użytkownika, wysłanie takiej wiadomości jest wykorzystaniem pewnej usługi. Piszemy wiadomość, podajemy numer i klikamy wyślij. To w jaki sposób wiadomość zostanie przekazana i ile za nią zapłacimy zależy między innymi od operatora sieci. Wkładając kartę SIM, możemy na starcie określić wspomniane warunki, aby później po uruchomieniu telefonu w każdej chwili korzystać z usługi w wybranej wersji.


Zastosowanie:

Wzorzec lokatora usług znajduje zastosowanie w sytuacji, gdy chcemy odseparować obiekty, od usług z których korzystają. Zwiększy to niezależność komponentów i ułatwi przyszłe wprowadzanie modyfikacji. Dodatkowo mając kilka podobnych serwisów, można wybierać któryś z nich przed uruchomieniem aplikacji przez odpowiednie ustawienia konfiguracyjne. Rozwiązanie takie wspiera testowalność.

Zasada działania:

Wprowadza się klasę lokatora usług, zawierającą statyczne pole typu HashTable z usługami. Kluczem do usługi w tablicy może być typ usługi lub podana nazwa. Dodatkowo klasa lokatora usług zawiera statyczne metody do pobrania i dodania nowego serwisu. Serwisy można dodawać na starcie aplikacji, np. w WPF czy Silverlight w metodzie OnStartup.

Przykład implementacyjny:

 public interface ILogger
    {
        void Write(string msg);
    }

    public class ConsoleLogger : ILogger
    {
        public void Write(string msg)
        {
            Console.WriteLine(msg);
        }
    }
internal class ServiceLocator
    {
        private static readonly Hashtable Services 
            = new Hashtable();

        public static void AddService<T>(T service)
        {
            Services.Add(typeof(T),service);
        }

        public static void AddService<T>(string name, T service)
        {
            Services.Add(name, service);
        }

        public static T GetService<T>()
        {
            return (T)Services[typeof(T)];
        }

        public static T GetService<T>(string name)
        {
            return (T)Services[name];
        }

    }
public class Fibonnaci
    {
        public int Number { get; set; }
        public int LastNum { get; set; }

        public Fibonnaci()
        {
            LastNum = 0;
            Number = 1;
        }

        public int Next()
        {
            var n = LastNum + Number;
            LastNum = Number;
            Number = n;
            IsDivisibleBy4();
            return n;
        }

        public void IsDivisibleBy4()
        {
            if (Number%4 != 0) return;
            var logger = ServiceLocator.GetService<ILogger>();
            logger.Write(String.Format
                             ("Number {0}, last : {1}",Number, LastNum));
        }
    }
class Program
    {
        static Program()
        {
            ServiceLocator.AddService<ILogger>(new ConsoleLogger());
        }

        static void Main(string[] args)
        {
            Fibonnaci fibonnaci = new Fibonnaci();
            for (int i = 0; i < 100; i++)
            {
                fibonnaci.Next();
            }
            Console.ReadKey();
        }
    }

czwartek, 5 lipca 2012

[Wzorce projektowe] Singleton

Analogia z życia:

Każde dziecko wie, że nieodłączną częścią każdego samochodu jest kierownica. Samochód zawiera dokładnie jedną kierownicę. Kierownica może być używana tylko przez jedną osobę, lub w ogóle nie używana. Gdyby kilka osób zaczęło kręcić kierownicą podczas jazdy to nietrudno sobie wyobrazić do czego by to doprowadziło. Gdyby samochód miał więcej kierownic. W najlepszym wypadku doszło by do czegoś takiego :-):



Zastosowanie:

Singletony tworzy się, gdy zachodzi potrzeba stworzenia dokładnie jednej instancji danej klasy. Dodatkowo wprowadza się blokowanie dwufazowe - zabezpieczenie instancji przed dostępem z wielu wątków. Obiekty - singletony podczas tworzenia nie potrzebują by przekazywać parametry za pomocą konstruktora. Czasami warto także zastanowić się nad stworzeniem singletonu gdy samo tworzenie obiektu jest kosztowne czasowo, a nie jest potrzebne wiele instancji.

Zasada działania:


Zazwyczaj tworzy się klasę zawierającą propercję lub polę pewnego typu. Klasa zewnętrzna posiada prywatny konstruktor i metodę zwracającą instancję obiektu z pola / propercji. Jeśli obiekt nie został wcześniej zainicjowany, to tworzy się instancję, która później jest zwracana przy każdym wywołaniu tej metody. Można użyć także klas statycznych, ale jest to odradzane ze względu na problemy z testowaniem i brak możliwości dziedziczenia.

Przykład:

Interfejs do zapisywania zmian do jakiegoś rejestru np logowanie wyjątków.

Przykład implementacyjny:

Poniższy singletonu wydaje się być optymalny ze względu na wydajność dla platformy .NET.




    public class ThreadSafeSingleton
    {
        private ThreadSafeSingleton()
        {
            
        }

        public static ThreadSafeSingleton Instance 
        {
            get { return NestedClass.instance; }
        }

        public void SayHello()
        {
            Console.WriteLine("How are you ?");
        }

        public class NestedClass
        {
            static NestedClass()
            {
            }

            internal static readonly ThreadSafeSingleton instance =
                new ThreadSafeSingleton();
        }
    }

class Program
    {
        static void Main(string[] args)
        {
            var inst = ThreadSafeSingleton.Instance;
            inst.SayHello();

        }
    }


Prywatny konstruktor zabrania tworzenia obiektów klasy. Statyczna propercja gwarantuje, że przekazywana będzie jedna referencja przy każdym wywołaniu, natomiast dzięki statycznemu konstruktorowi klasy zagdnieżdżonej obiekt zostanie zainicjowany dopiero przy pierwszym jego wywołaniu (Lazy Loading). Pole readonly zapewnia bezpieczeństwo przy pracy wielowątkowej i jest to podejście szybsze od stosowania instrukcji lock.

Linki:

1.Readonly a thread safe