Design Pattern Trong Ruby
Bài đăng này đã không được cập nhật trong 8 năm
Design patterns là các giải pháp đã được tối ưu hóa, được tái sử dụng cho các vấn đề lập trình mà chúng ta gặp phải hàng ngày.
Một design patterns không phải là một Class hoặc một Library
Nó là một khuôn mẫu đã được thực hiện. Nó không phải là ngôn ngữ cụ thể nào cả.
Một design patterns có thể thực hiện được ở phần lớn các ngôn ngữ lập trình
Có rất nhiều các Design Pattern khác nhau:
- Template Method
- Strategy
- Observer
- Composite
- Iterator
- Commands
- Adapter
- Proxy
- Decorator
- Singleton
- Factory
- Abstract Factory
- Builder
- Interpreter
Dưới đây là 2 trong số chúng
I. Observer Pattern
I.1. Khái niệm
Observer pattern được sử dụng khi xây dựng hệ thống mà ở đó trạng thái của một objectt bị ảnh hưởng bởi trạng thái của một object khác. Excel là một ví dụ hay cho Observer Pattern. Giả sử bạn có một cột các số và có một ô để tính tổng các ô số trong cột đó, thì khi một trong những ô số thay đổi sẽ làm ảnh hưởng, thay đổi ô tính tổng.
I.2. Sử dụng Observer Pattern
Gỉa sử ta có một ứng dụng đơn giản theo dõi tổng số km mà xe đã đi và sẽ thông báo xe cần bảo dưỡng khi xe đã chạy tới một mức nào đó.
Đầu tiên ta sẽ tạo ra một class Notifier như một observer. Và nhất thiết ta phải định nghĩa một update()
method bên trongNotifier
bởi Module Obserabable sẽ có callback gọi hàm này mỗi khi có đối tượng thay đổi.
class Notifier
def update(car, miles)
puts "The car has logged #{miles} miles, totaling #{car.mileage} miles traveled."
puts "The car needs to be taken in for a service!" if car.service <= car.mileage
end
end
Mỗi khi observer nhận được thông báo tức là có sự thay đổi thì callback của Obserabable
sẽ gọi và in ra thông báo.
Tiếp đến ta sẽ tạo ra một class Car
require 'observer'
class Car
include Observable
attr_reader :mileage, :service
def initialize(mileage = 0, service = 3000)
@mileage, @service = mileage, service
add_observer(Notifier.new)
end
def log(miles)
@mileage += miles
if @mileage >= self.service
changed
notify_observers(self, miles)
end
end
end
Chạy trên console
2.1.5 :002 > ca = Car.new
=> #<Car:0x0000000230e858 @service=3000, @mileage=0, @observer_peers={#<Notifier:0x0000000230e830>=>:update}>
2.1.5 :003 > ca.log(100)
=> nil
2.1.5 :004 > ca.log(3001)
The car has logged 3001 miles, totaling 3101 miles traveled.
The car needs to be taken in for a service!
=> false
2.1.5 :005 >
II.Singleton Pattern
II.1 Khái niệm
Singleton là một design pattern nó giớ hạn veiejc tạo object của class, chỉ một object được tạo. Nó rất hữu ích khi bạn cần một instance truy cập vào những phần khác nhau của ứng dụng.
class AppConfig
attr_accessor :data
@@instance = AppConfig.new
def self.instance
return @@instance
end
def version
'1.0.0'
end
private_class_method :new
end
Ví dụ trên cho thấy ta có thể truy cập vào một instance thông qua một class method chỉ một instance được tạo ra.
II.2 Ruby Single module
Ruby có một module có để thực thi Singleton Patttern đó là Singeleton module. Ta có thể rút gọn lại ví dụ trên bằng việc sử dụng module Singleton
require 'singleton'
class AppConfig
include Singleton
attr_accessor :data
def version
'1.0.0'
end
end
2.1.5 :021 > load 'config_singleton.rb'
=> true
2.1.5 :022 > AppConfig.instance.data = {enabled: true}
=> {:enabled=>true}
2.1.5 :023 > AppConfig.instance.version
=> "1.0.0"
2.1.5 :024 > second = AppConfig.instance
=> #<AppConfig:0x00000002017cd0 @data={:enabled=>true}>
2.1.5 :025 > second.data = {enabled: false}
=> {:enabled=>false}
2.1.5 :026 > AppConfig.instance.data
=> {:enabled=>false}
Qua việc chạy trên cho thấy chỉ một instance được tao ra thông qua việc gọi class method instance
và được sử dụng global.
Nguồn tham khảo
All rights reserved