Skip to main content

Service Locator pattern

Service Locator là một design pattern thông dụng cho phép tách rời (decouple) một class với các dependency (hay được gọi là service) của nó. Service Locator có thể coi là một đối tượng trung gian trong việc liên kết class và các dependency.

Giới thiệu

Service-Locator-Pattern
Serive Locator pattern mô tả cách để đăng ký và lấy các dependency để sử dụng. Bạn có thể thấy pattern này là một dạng kết hợp của Factory pattern và Dependency Injection pattern. Một số lợi ích mà pattern này đem lại:
– Tách rời một class với các dependency của nó, nhờ đó có thể dễ dàng thay thế các dependency.
– Các dependency sẽ được sử dụng dưới dạng interface, đảm bảo không sử dụng các class cụ thể (concrete)của dependency.
– Dễ dàng test các class trong môi trường cách ly (isolation), không phụ thuộc vào các dependency.
– Các đoạn code để tạo, quản lý dependency được tách riêng ra khỏi các class.
– Ứng dụng có thể được chia ra các phần ít bị ràng buộc (loosely coupled) với nhau.
Mặc dù có nhiều lợi ích rõ ràng như vậy nhưng pattern cũng có một số hạn chế và nhiều ý kiến trái chiều. Tuy nhiên bài viết này chỉ tập trung vào giới thiệu và minh họa cơ chế làm việc của nó.

Hiện thực một Service Locator

Dưới đây là một ví dụ cách hiện thực lớp Service Locator sử dụng generic trong C#. Nó chứa hai phương thức quan trọng mà bạn cần quan tâm:
– Register<T>: đăng ký một dependency dựa trên kiểu của interface (T) và một instance hiện thực từ interface đó (service). Service Locator sẽ giữ lại trong cache để trả về khi được yêu cầu.
– GetService<T>(): trả về một service được đăng ký với kiểu T.
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
public class ServiceLocator
{
    private static readonly IDictionary<Type, object> _serviceCache;
    private static ServiceLocator _instance;
    static ServiceLocator()
    {
        _serviceCache = new Dictionary<Type, object> ();
    }
    public static ServiceLocator Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new ServiceLocator();
            }
            return _instance;
        }
    }
    public void Register<T>(T service)
    {
        var key = typeof(T);
        if (!_serviceCache.ContainsKey(key))
        {
            _serviceCache.Add(key, service);
        }
        else  // overwrite the existing instance.
        {
            _serviceCache[key] = service;
        }
    }
    public T GetService<T>()
    {
        var key = typeof(T);
        if (!_serviceCache.ContainsKey(key))
        {
            throw new ArgumentException(string.Format("Type '{0}' has not been registered.", key.Name));
        }
        return (T)_serviceCache[key];
    }
}

Ví dụ sử dụng

Một ví dụ đơn giản sử dụng ServiceLocator bên trên, interface IOperatingSystem được sử dụng như một dependency. Tôi tạo thêm một class Windows hiện thực từ interface này.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public interface IOperatingSystem
{
    string Name { get; set; }
    void Run();
}
public class Windows : IOperatingSystem
{
    public Windows()
    {
        Name = "Windows XP";
    }
    public string Name { get; set; }
    public void Run()
    {
        Console.WriteLine(Name + " is running.");
    }
}
Tiếp theo là class Computer sẽ sử dụng dependency IOperatingSystem. Trong constructor của class này, tôi sẽ lấy instance của IOperatingSystem từ ServiceLocator, tất nhiên nó phải được đăng ký trước. Với cách này, bạn thấy nó sẽ khác biệt với dependency injection truyền parameter thông qua constructor.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Computer
{
    private readonly IOperatingSystem _operatingSystem;
    public Computer()
    {
        _operatingSystem = ServiceLocator.Instance.GetService<IOperatingSystem>();
    }
    public void Start()
    {
        _operatingSystem.Run();
    }
}
Dưới đây là đoạn code chương trình để chạy minh họa. Như bạn thấy việc tạo một instance của Computer rất dễ dàng vì bạn không cần thiết phải tạo và truyền các dependency cho nó.
1
2
3
4
5
6
7
8
9
static void Main(string[] args)
{
    ServiceLocator.Instance.Register<IOperatingSystem>(new Windows());
     
    var computer = new Computer();
    computer.Start();
    Console.Read();
}
Output:
Windows XP is running.
Đọc thêm

Comments

Popular posts from this blog

Merge AVHDX Hyper-V Checkpoints

When you create a snapshot of a virtual machine in Microsoft Hyper-V, a new file is created with the  .avhdx  file extension. The name of the file begins with the name of its parent VHDX file, but it also has a GUID following that, uniquely representing that checkpoint (sometimes called snapshots). You can see an example of this in the Windows Explorer screenshot below. Creating lots of snapshots will result in many  .avhdx  files, which can quickly become unmanageable. Consequently, you might want to merge these files together. If you want to merge the  .avhdx  file with its parent  .vhdx  file, it’s quite easy to accomplish. PowerShell Method Windows 10 includes support for a  Merge-VHD  PowerShell command, which is incredibly easy to use. In fact, you don’t even need to be running PowerShell “as Administrator” in order to merge VHDX files that you have access to. All you need to do is call  Merge-VHD  with the  -Path  parameter, pointing to the  .avhdx  file, and the  -Des

Openstack manila phần 4: Native GlusterFS Driver

Tiếp tục loạt bài về Openstack Manila hôm nay tôi sẽ cấu hình backend sử dụng GlusterFS Yêu cầu phiên bản GlusterFS >= 3.6. Với glusterfs nếu cluster của bạn không hỗ trợ snapshot thì trên manila cũng sẽ mất đi tính năng này. Để cấu hình snapshot ta sẽ cấu hình Thin Provision theo bài hướng dẫn link Với bài lab của mình có 2 node và chạy kiểu replicate. Mình sẽ tạo các thinly provisioned và tạo volume trên đó. Mô hình cài đặt Cài đặt glusterfs-v3.7 add-apt-repository ppa:gluster/glusterfs-3.7 -y apt-get update apt-get install glusterfs-server -y Tham khảo script tạo thin LV và gluster volume Script tạo thinly provisioned chạy trên 2 node apt-get install xfsprogs -y pvcreate /dev/sdb vgcreate myVG /dev/sdb lvcreate -L 8G -T myVG/thinpool for ((i = 1;i<= 5; i++ )) do mkdir -p /manila/manila-"$i" for (( j = 1; j<= 5; j++)) do lvcreate -V "${i}"Gb -T myVG/thinpool -n vol-"$i"-"$j" mkfs.xfs /dev/my

Zabbix, AWS and Auto Registration

One of the things I love the most with AWS is  auto-scaling . You choose an AMI, set some parameters and AWS will spin instances up and down whenever a threshold is breached. But with all these instances spinning up and down there are some unknowns. For example, what is the IP address of the new instance? Its host name? This can be critical when other components of your infrastructure are dependent on knowing these parameters. I had this problem when I started to use  Zabbix  as the monitoring system. At first it seemed like a complicated one, but Zabbix has a wonderful feature called  Auto Registration  which can be used exactly for this situation. I will try to show how to configure auto registration both on the client (EC2 instance running Ubuntu 14.04) and on the Zabbix server (Zabbix Server 2.4.2). Zabbix-agent Installation and Configuration Let’s start with installing zabbix-agent on the Ubuntu client: 1 2 $ sudo apt-get update $ sudo apt-get install -y zab