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

środa, 15 sierpnia 2012

[WPF] Dependency Property

Jedną z najważniejszych koncepcji w WPF jest Dependency Property. Umożliwiają one stylowanie, automatyczny data binding czy animowanie dowolnych właściwości. Dependency Property może być zmieniane przez wiele obiektów jednocześnie, a jego największą zaletą jest wbudowana zdolność do notyfikowania o zmianach wartości. DP mogą być także zmieniane z poziomu xaml co jest następną ich zaletą. Zatem przy tworzeniu własnych kontrolek jest to bardzo wygodne rozwiązanie. Kolejną korzyścią wynikającą z zastosowania DP jest możliwosć zdefiniowania Property Triggerów - warunkowych akcji wykonywanych, gdy property osiągnie pewną wartość

Od strony języka DP są propertiesami, budowanymi w dość nietypowy sposób. Należy dodać do klasy kontrolki statyczne publiczne pole tylko do odczytu, gdzie nazwa to nazwa property z dodanym "Property". Następnie w statycznym konstruktorze rejestruje się DP za pomocą metody DependencyProperty.Register. Przez parametry tej metody można określić domyślną wartość i metodę wołaną przy zmianie wartości. Można także zdefiniować pewien "wrapper", który będzie opakowywał ustawianie i odczyt wartości DP.

W poniższym przykładzie dla kontrolki tykającego zegarka zdefiniowano Dependency Property Ticks, które reprezentuje liczbę uderzeń zegarka.

 public partial class TickingTimer : UserControl
    {

        public static readonly DependencyProperty TicksProperty;

        public int Ticks
        {
            get { return (int)GetValue(TickingTimer.TicksProperty); }
            set { SetValue(TickingTimer.TicksProperty, value); }
        }

        static TickingTimer()
        {
            TickingTimer.TicksProperty = DependencyProperty.Register("Ticks",
                typeof(int), typeof(TickingTimer),
                new FrameworkPropertyMetadata(0,
                new PropertyChangedCallback(OnTicksChanged)));
        }

        private static void OnTicksChanged(DependencyObject o, DependencyPropertyChangedEventArgs eventArgs)
        {
            Console.Beep();
        }
//LOGIKA KONTROLKI
     }

Kontrolkę taką można dodać do okna i zbindować się do naszego Dependency Property Ticks.

<Window x:Class="Dependency_Property.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:Dependency_Property="clr-namespace:Dependency_Property" 
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Dependency_Property:TickingTimer x:Name="Timer" Ticks="5" />
        <Label Content="{Binding ElementName=Timer,  Path=Ticks}" />
    </Grid>
</Window>

poniedziałek, 23 lipca 2012

[Wzorce projektowe] Null Object

Analogia z życia:

Każdy użytkownik komunikatora gadu - gadu ma do dyspozycji kilka statusów. Może być np. dostępny lub niewidoczny. Mając na liście znajomych, nie możemy w prosty sposób rozróżnić kto z nich jest niewidoczny, a kogo nie ma w danej chwili przy komputerze. Komunikator zapewnia jednak, że możemy wysłać wiadomość do każdego z nich : jeśli użytkownik jest przy komputerze, to może nam błyskawicznie odpisać, natomiast gdy go nie ma, wiadomość nie zaginie, lecz zostanie mu dostarczona po zalogowaniu do komunikatora.



Zastosowanie:

Wzorca Null Object można użyć, gdy mamy do czynienia z dużą ilością obiektów, które w pewnym etapie programu mają wartość null. Aby uniknąć wyjątku NullReference oraz sprawdzeń, czy dany obiekt jest nullem, można wprowadzić dodatkowy obiekt bez jakiejkolwiek funkcjonalności, np. zawierający puste metody tego samego interfejsu co zwykły obiekt. Kolejnym powodem, dla którego warto zastosować ten wzorzec jest sytuacja, w której klient pobiera obiekty i nie chcemy, aby zajmował się sprawdzaniem, czy ich wartość jest równa null.

Zasada działania:

Obiekt klienta przechowuje referencję do obiektu typu pewnej klasy abstrakcyjnej. Z tej klasy dziedziczą dwa typy : rzeczywisty obiekt i obiekt - null. Można także wprowadzić kilka obiektów null jako reprezentację różnych stanów "nieaktywności". W niektórych przypadkach warto rozważyć zastosowanie singletonu, jako obiektu - null.

Przykład implementacyjny:

public class Fire
    {
        public int Power { get; set; }
    }

    public abstract class FirefighterBase
    {
        public abstract void Distinguish(Fire fire);

        static InactiveFirefighter _inactive = new InactiveFirefighter();

        public static FirefighterBase NULL
        {
            get { return _inactive; }
        }

        public class InactiveFirefighter : FirefighterBase
        {
            public override void Distinguish(Fire fire)
            {
                Console.WriteLine("Cannot help you");
            }
        }
    }

    public class ActiveFirefighter : FirefighterBase
    {
        private int _strength;

        public ActiveFirefighter()
        {
            Random r = new Random();
            _strength = r.Next() % 25;
        }

        public override void Distinguish(Fire fire)
        {
            fire.Power -= _strength;
            Console.WriteLine("Distinguishing...");
        }
    }
 public static class FireBrigade
    {
        public static FirefighterBase GetFireFighter(int id)
        {
            if(id % 2 ==0)
            {
                return FirefighterBase.NULL;
            }
            else
            {
                return new ActiveFirefighter();
            }
        }
    }
class Program
    {
        static void Main(string[] args)
        {
            Fire f = new Fire() {Power = 300};
            List<FirefighterBase> fighters = new List<FirefighterBase>();
            for (int i = 0; i < 15; i++)
            {
                fighters.Add(FireBrigade.GetFireFighter(i));
            }
            foreach (FirefighterBase firefighterBase in fighters)
            {
                firefighterBase.Distinguish(f);
            }

            Console.WriteLine(String.Format("Fire power is now... {0}",f.Power));

            Console.ReadKey();
        }
    }

poniedziałek, 26 grudnia 2011

[Ada | EN] Circular buffer using protected object

Theme
How to implement circular buffer in Ada programming language with use of protected object.

Circular buffer is a simple data structure that contains an fixed size array and two data pointers (start of valid data and the end of valid data). Protected object provides mutual exclusion of two synchronous tasks (Producer and Consumer). Data inside buffer is being modified by calling (with random delay times) one of two entries (Add, Take). Each of them contains a when statement that ensures data cohesion. If one of entries is being called and a condition associated with apropriate when statement is not fullfilled, the task is being suspended until the condition is done.

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
with Ada.Text_Io;
use Ada.Text_Io;
with Ada.Numerics.Discrete_Random;
 
 
procedure Cyclic_Buffer is
 
   type Buffer is array (Integer range <>) of Integer;
   Size : Integer:=5;
 
   subtype Wait is Integer range 0..5;
   package Draw is new Ada.Numerics.Discrete_Random(Wait);
   use Draw;
   G : Generator;
 
   protected Protected_Buffer is
      entry Add(I : in Integer);
      entry Take(I : out Integer);
   private 
      B : Buffer(1..Size);   
      Counter : Integer:=0;
      GetIndex : Integer:=1;
      PutIndex : Integer:=1;
         
 end Protected_Buffer;
   
   task Producer;
   task Consumer;
 
   protected body Protected_Buffer is
 
      entry Add(I : in Integer) when Counter < Size is
      begin
         B(PutIndex) := I;
         PutIndex := PutIndex mod Size + 1;
         Counter := Counter + 1;                   
         end Add;
 
      entry Take(I : out Integer) when Counter > 0 is
      begin
         I:=B(GetIndex);
         GetIndex := GetIndex mod Size + 1;  
         Counter := Counter - 1;      
         end Take;
   end Protected_Buffer;   
   
 
 
task body Consumer is
   Cons_Delay_Time : Integer;
begin
   loop
      Reset(G);
      Cons_Delay_Time:=Integer(Random(G));
      delay Duration(1.3*Float(Cons_Delay_Time));
      Protected_Buffer.Take(Cons_Delay_Time);
      Put_Line("Consumer : Taking "&Cons_Delay_Time'Img);
      delay 0.15;
    end loop;
end Consumer;
 
task body Producer is
   Prod_Delay_Time : Integer;
begin
   loop
      Reset(G);
      Prod_Delay_Time := Integer(Random(G));
      delay Duration(Prod_Delay_Time);
      Protected_Buffer.Add(Prod_Delay_Time);
      Put_Line("Producer : Adding "&Prod_Delay_Time'Img);
      delay 0.15;
   end loop;
end Producer;
 
begin
   null;
end Cyclic_Buffer;

Comments:
[11 - 14] Random number generator declaration. It draws consecutive delay times for both tasks.
[27 - 28] Tasks are being triggered
[55] Delay time depends on a drawn number
[56] Local variable associates now with a value from the buffer
[77] All the instructions are being evolved in tasks so null instruction is here sufficient

Compiler: Ideone.com

niedziela, 25 grudnia 2011

[Ada | PL] Bufor cykliczny na obiekcie chronionym

Temat:
Realizacja bufora cyklicznego w języku Ada z wykorzystaniem obiektu chronionego.

Bufor cykliczny to prosta struktura danych zrealizowana w przypadku tego programu na tablicy pięcioelementowej, gdzie dane dodawane są i pobierane zgodnie z indeksami wskaźników (w programie GetIndex i PutIndex). Obiekt chroniony zapewnia wzajemne wykluczanie dostępu do zasobów dwóch współbieżnie działających zadań (producenta i konsumenta). Modyfikowanie danych w tablicy dokonuje się za pomocą dwóch instrukcji entry wywoływanych z obu zadań w losowych chwilach czasu. Instrukcje te zapewniają nie tylko synchronizację zadań, ale także zawieszenie zadania, jeśli nie jest spełniony warunek zapisany instrukcją when. Zadanie zostaje odwieszone, gdy warunek ponownie zostanie spełniony.



1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
with Ada.Text_Io;
use Ada.Text_Io;
with Ada.Numerics.Discrete_Random;
 
 
procedure Cyclic_Buffer is
 
   type Buffer is array (Integer range <>) of Integer;
   Size : Integer:=5;
 
   subtype Wait is Integer range 0..5;
   package Draw is new Ada.Numerics.Discrete_Random(Wait);
   use Draw;
   G : Generator;
 
   protected Protected_Buffer is
      entry Add(I : in Integer);
      entry Take(I : out Integer);
   private 
      B : Buffer(1..Size);   
      Counter : Integer:=0;
      GetIndex : Integer:=1;
      PutIndex : Integer:=1;
         
 end Protected_Buffer;
   
   task Producer;
   task Consumer;
 
   protected body Protected_Buffer is
 
      entry Add(I : in Integer) when Counter < Size is
      begin
         B(PutIndex) := I;
         PutIndex := PutIndex mod Size + 1;
         Counter := Counter + 1;                   
         end Add;
 
      entry Take(I : out Integer) when Counter > 0 is
      begin
         I:=B(GetIndex);
         GetIndex := GetIndex mod Size + 1;  
         Counter := Counter - 1;      
         end Take;
   end Protected_Buffer;   
   
 
 
task body Consumer is
   Cons_Delay_Time : Integer;
begin
   loop
      Reset(G);
      Cons_Delay_Time:=Integer(Random(G));
      delay Duration(1.3*Float(Cons_Delay_Time));
      Protected_Buffer.Take(Cons_Delay_Time);
      Put_Line("Consumer : Taking "&Cons_Delay_Time'Img);
      delay 0.15;
    end loop;
end Consumer;
 
task body Producer is
   Prod_Delay_Time : Integer;
begin
   loop
      Reset(G);
      Prod_Delay_Time := Integer(Random(G));
      delay Duration(Prod_Delay_Time);
      Protected_Buffer.Add(Prod_Delay_Time);
      Put_Line("Producer : Adding "&Prod_Delay_Time'Img);
      delay 0.15;
   end loop;
end Producer;
 
begin
   null;
end Cyclic_Buffer;

Komentarze:
[11 - 14] Deklaracje generatora liczb pseudolosowych, który odpowiada za losowe czasy opóźnienia w działaniu obu zadań (od 0 do 5 sek).
[27 - 28] Uruchomienie wykonywania zadań
[55] Opóźnienie wykonywania zadania zależne od wylosowanej liczby
[56] Pobranie z bufora wartości do zmiennej lokalnej
[77] Pusta instrukcja programu - wszystkie instrukcje wykonują się w dwóch współbieżnych zadaniach

Kompilator: Ideone.com