Chương 12: Kết hợp design pattern – MVC Pattern – Mẫu của các mẫu (P2)

Elvis có một “mẫu kết hợp” (kết hợp các design pattern), anh ấy sẽ đặt tên cho chúng là là Model-View-Controller, và anh ấy sẽ hát một bài hát nhỏ như thế này…

Model View Controller
Lyrics and music: James Dempsey

MVC’s a paradigm for factoring your code into functional segments, so your brain does not explode.
To achieve reusability, you gotta keep those boundaries clean Model on the one side, View on the other, the Controller’s in between.
Model View, it’s got three layers like Oreos
Model View Controller
Model View, Model View, Model View Controller
Model objects represent your application’s raison d’être
Custom objects that contain data, logic, and et cetera
You create custom classes, in your app’s problem domain
you can choose to reuse them with all the views
but the model objects stay the same.
You can model a throttle and a manifold
Model the toddle of a two year old
Model a bottle of fine Chardonnay
Model all the glottal stops people say
Model the coddling of boiling eggs
You can model the waddle in Hexley’s legs
Model View, you can model all the models that pose for GQ
Model View Controller
View objects tend to be controls used to display and edit
Cocoa’s got a lot of those, well written to its credit.
Take an NSTextView, hand it any old Unicode string
The user can interact with it, it can hold most anything
But the view don’t know about the Model
That string could be a phone number or the works of Aristotle
Keep the coupling loose and so achieve a massive level of reuse
Model View, all rendered very nicely in Aqua blue
Model View Controller
You’re probably wondering now
You’re probably wondering how
Data flows between Model and View
The Controller has to mediate
Between each layer’s changing state
To synchronize the data of the two
It pulls and pushes every changed value
Model View, mad props to the smalltalk crew!
Model View Controller
Model View, it’s pronounced Oh Oh not Ooo Ooo
Model View Controller
There’s a little left to this story
A few more miles upon this road
Nobody seems to get much glory
From writing the controller code
Well the model’s mission critical
And gorgeous is the view
I might be lazy, but sometimes it’s just crazy
How much code I write is just glue
And it wouldn’t be so tragic
But the code ain’t doing magic
It’s just moving values through
And I don’t mean to be vicious
But it gets repetitious
Doing all the things controllers do
And I wish I had a dime
For every single time
I sent a TextField StringValue.
Model View
How we gonna deep six all that glue
Model View Controller
Controllers know the Model and View very intimately
They often use hardcoding which can be foreboding for reusability
But now you can connect each model key that you select to any view property
And once you start binding
I think you’ll be finding less code in your source tree
Yeah I know I was elated by the stuff they’ve automated the things you get for free
And I think it bears repeating all the code you won’t be needing when you hook it up in IB.
Model View, even handles multiple selections too
Model View Controller
Model View, bet I ship my application before you
Model View Controller
Model View Controller
Nhạc và lời: James Dempsey

MVC là một mẫu để chia code của bạn thành các phần chức năng,để não của bạn sẽ không bị nổ tung.
Để đạt được khả năng tái sử dụng, bạn phải giữ cho các ranh giới đó rõ ràng Model ở một bên, View ở bên kia, Controller sẽ ở giữa.
Model View, nó có ba lớp giống bánh Oreo
Model View Controller
Model View, Model View, Model View Controller
Model object đại diện cho raison d’être của ứng dụng
Các object tùy chỉnh chứa dữ liệu, cả logic và vân vân…
Bạn tạo custom classes, trong problem domain của ứng dụng
bạn có thể chọn dùng lại chúng với tất cả views
nhưng các Model vẫn được giữ nguyên.
Bạn có thể model một throttle và manifold
Làm cho Model trẻ đi hai tuổi
Model một chai Chardonnay ngon
Model tất cả thứ mà mọi người nói
Model hóa những cái trứng luộc
Bạn model thuyền buồm Hexley’s legs
Model View, bạn có thể model tất cả các model cho GQ
Model View Controller
View object thường được Controller dùng display và edit
Cocoa có rất nhiều trong số đó, được ghi nhận tốt.
Lấy NSTextView, giao nó bất kỳ chuỗi Unicode cũ
Người dùng có thể tương tác với nó, nó có thể chứa mọi thứ
Nhưng View không biết về Model
String có thể là số điện thoại hoặc các tác phẩm của Aristotle
Giữ cho khớp nối “lỏng lẻo” và do đó đạt mức độ tái sử dụng lớn
Model View, tất cả được hiển thị đẹp bằng màu xanh
Model View Controller
Bây giờ có lẽ bạn đang tự hỏi
Có thể bạn đang tự hỏi làm thế nào
Luồng dữ liệu giữa Model và View
Controller phải làm trung gian
Giữa trạng thái thay đổi của mỗi lớp
Để đồng bộ hóa dữ liệu cả hai
Nó kéo và đẩy mọi giá trị đã thay đổi
Model View, công cụ cho cuộc giao tiếp nhỏ!
Model View Controller
Model View, nó phát âm là Oh Oh not Ooo Ooo
Model View Controller
Còn lại một chút cho câu chuyện này
Một vài dặm trên con đường này
Dường như không ai đạt nhiều vinh quang
Từ việc viết controller code
Vâng, sứ mệnh của model rất quan trọng
Và tuyệt đẹp là View
Tôi có thể lười, nhưng đôi khi nó thật điên rồ
Tôi viết bao nhiêu code như là “keo”
Và nó sẽ không bi thảm như vậy
Nhưng code không hoạt động kỳ diệu
Nó chỉ di chuyển thông qua value
Và tôi không có ý xấu
Nhưng nó lặp đi lặp lại
Làm tất cả những điều controller làm
Và tôi ước mình có 1 xu
Cho mọi lần
Tôi đã gửi một TextField StringValue.
Model View
How we gonna deep six all that glue
Model View Controller
Controllers hiểu biết rất rõ về Model và View
Chúng thường sử dụng code cứng, thứ có thể được mã hóa để dùng lại
Nhưng bây giờ có thể kết nối model key
chọn với bất kỳ view property
Và một khi bạn bắt đầu binding
Tôi nghĩ rằng bạn sẽ thấy ít code hơn trong source
Vâng, tôi biết tôi đã rất phấn khích bởi họ đã tự động hóa những thứ bạn nhận miễn phí
Và tôi nghĩ rằng nó sẽ lặp lại tất cả code bạn sẽ không cần khi kết nối (hook) nó trong IB.
Model View, thậm chí cũng xử lý nhiều lựa chọn
Model View Controller
Model View, cá là tôi gửi ứng dụng của tôi trước bạn
Model View Controller
Nhờ các bạn đóng góp lời dịch cho bài hát
Kết hợp các design pattern như chiếc bánh Oreo

Không. Mẫu thiết kế là chìa khóa của bạn đối với MVC.

Chúng tôi chỉ cố gắng kích thích sự “thèm ăn” của bạn. Sau khi bạn đọc xong chương này, hãy quay lại và nghe lại bài hát – bạn sẽ thấy còn thú vị hơn nữa.
Có vẻ như trước đây bạn đã gặp khó khăn khi học mẫu MVC? Hầu hết chúng ta đều như vậy. Bạn có thể đã nghe những Dev khác nói với bạn rằng MVC đã thay đổi cuộc đời họ và có thể tạo ra “hòa bình thế giới”. Chắc chắn đó là một mẫu “phức hợp” mạnh mẽ và mặc dù chúng tôi không thể khẳng định nó sẽ tạo ra hòa bình thế giới, nhưng nó sẽ giúp bạn tiết kiệm hàng giờ viết code, khi bạn biết về nó.
Nhưng trước tiên bạn phải tìm hiểu MVC, phải không? Chà, sẽ có sự khác biệt rất lớn nếu bạn đã biết về các mẫu thiết kế!
Đúng vậy, các mẫu thiết kế khác là “chìa khóa” của MVC. Chỉ học riêng MVC sẽ rất khó; không nhiều Dev thành công bằng cách học này. Đây là bí quyết để học MVC: MVC chỉ là một vài Design pattern khác được ghép lại với nhau. Khi bạn tiếp cận việc học MVC bằng cách xem xét các design pattern khác, thì đột nhiên MVC bắt đầu dễ hiểu.
Bắt đầu nào. Lần này, bạn sẽ hiểu được MVC!

Xem qua Model-View-Controller

Hãy tưởng tượng bạn đang sử dụng máy nghe nhạc MP3 yêu thích của mình, chẳng hạn như iTunes. Bạn có thể sử dụng các chức năng của nó để thêm các bài hát mới, quản lý danh sách phát và đổi tên các bản nhạc. Trình phát sẽ đảm bảo việc duy trì một cơ sở dữ liệu nhỏ về tất cả các bài hát của bạn cùng với tên và dữ liệu liên quan của chúng. Nó cũng quản lý việc phát các bài hát và giao diện người dùng được cập nhật liên tục với tên bài hát hiện tại, thời gian chạy, v.v.
Chà, code bên trong nó chính là Model-View-Controller …

Sơ đồ trạng thái mẫu MVC

Một cái nhìn sâu hơn

Mô tả của MP3 Player cung cấp cho chúng ta cái nhìn tổng quát về MVC, nhưng nó thực sự không giúp bạn hiểu rõ ràng về cách thức hoạt động của chúng, cách bạn xây dựng hoặc “tại sao nó lại là một điều tốt?”. Hãy bắt đầu bằng cách xem qua các mối quan hệ giữa Model, View và Controller, sau đó chúng ta sẽ xem xét từ quan điểm của Mẫu thiết kế.

1. Bạn là người dùng – bạn tương tác với View.

View là cửa sổ của bạn tới Model. Khi bạn làm điều gì đó với View (như nhấp vào nút Play) thì View sẽ cho Controller biết bạn đã làm gì. Công việc của Controller là xử lý điều đó.

2. Controller yêu cầu Model thay đổi trạng thái của nó

Controller thực hiện các hành động của bạn và diễn giải chúng. Nếu bạn nhấp vào một button, công việc của Controller là tìm ra điều đó có nghĩa là gì, và Model sẽ được điều khiển như thế nào dựa trên hành động đó.

3. Controller cũng có thể yêu cầu view thay đổi.

Khi Controller nhận được một hành động từ View, nó có thể cần yêu cầu View thay đổi. Ví dụ, Controller có thể bật hoặc tắt một số nút hoặc chọn menu trong giao diện.

4. Model thông báo cho View khi trạng thái của nó đã thay đổi.

Khi có điều gì đó thay đổi trong Model, dựa trên một số hành động bạn đã thực hiện (như nhấp vào nút) hoặc một số thay đổi nội bộ khác (như bài hát tiếp theo trong danh sách phát đã bắt đầu), Model sẽ thông báo cho View rằng trạng thái của nó đã thay đổi.

5. View yêu cầu Model cho trạng thái.

View có trạng thái hiển thị trực tiếp từ Model. Ví dụ: khi Model thông báo cho View rằng một bài hát mới đã bắt đầu phát, View sẽ yêu cầu tên bài hát từ Model và hiển thị nó. View cũng có thể yêu cầu Model cho trạng thái do Controller yêu cầu một số thay đổi trong View.

Không có câu hỏi ngớ ngẩn

Hỏi: Controller có bao giờ trở thành observer của Model không?
Đáp: Chắc chắn. Trong một số thiết kế, Controller đăng ký với Model và được thông báo về những thay đổi. Đây có thể là trường hợp khi một cái gì đó trong Model ảnh hưởng trực tiếp đến các điều khiển giao diện người dùng. Ví dụ: một số trạng thái nhất định trong Model có thể yêu cầu một số mục giao diện được bật hoặc tắt. Nếu vậy, việc của Controller thực sự là yêu cầu View cập nhật màn hình cho phù hợp.

Hỏi: Tất cả những gì Controller làm là lấy input của người dùng từ View và “gửi nó đến Model”, đúng không? Tại sao lại có Controller làm gì, nếu đó là tất cả những gì nó làm? Tại sao không code trực tiếp trong View? Trong hầu hết các trường hợp, không phải Controller chỉ gọi một phương thức trên Model?
Đáp: Controller không chỉ “gửi nó đến Model”, Controller chịu trách nhiệm diễn giải đầu vào và thao tác với Model dựa trên đầu vào đó. Nhưng câu hỏi thực sự của bạn có lẽ là “tại sao tôi không thể làm điều đó trong View?” Bạn có thể làm như vậy; tuy nhiên, bạn sẽ không muốn vì hai lý do: Thứ nhất, bạn sẽ làm phức tạp View của mình vì lúc này view sẽ có hai trách nhiệm: quản lý giao diện người dùng và xử lý logic về cách kiểm soát Model. Thứ hai, bạn đang gắn chặt View của mình với Model. Nếu bạn muốn sử dụng lại View với một Model khác, sẽ không thể. Controller tách logic điều khiển khỏi View và tách View khỏi Model. Bằng cách giữ cho View và Controller được ghép nối một cách “lỏng lẻo”, bạn đang xây dựng một thiết kế linh hoạt và có thể mở rộng hơn, một thiết kế có thể dễ dàng thích ứng với những thay đổi trong tương lai.

Nhìn MVC qua lăng kính của các Pattern

Chúng tôi đã cho bạn biết cách tốt nhất để học MVC là xem MVC như một tập hợp các mẫu thiết kế hoạt động cùng nhau. Hãy bắt đầu với Model. Như bạn có thể đoán được, Model sử dụng mẫu Observer để cập nhật các ViewController cho các thay đổi trạng thái mới nhất.
Mặt khác, ViewController áp dụng Strategy Pattern. Controller là một “hành vi” của View (như ở Chương 1, Bay là một hành vi của Duck) và nó có thể dễ dàng được trao đổi với một Controller khác nếu bạn muốn hành vi khác. Bản thân View cũng sử dụng một mẫu bên trong để quản lý các cửa sổ, nút và các thành phần khác của màn hình: Mẫu Composite.
Hãy xem xét kỹ hơn:

Sử dụng MVC để điều khiển beat nhạc…

Đã đến lúc bạn trở thành DJ. Khi bạn là một DJ, tất cả về chúng là nhịp điệu. Bạn có thể bắt đầu bản mix của mình với một cài đặt downtempo chậm lại ở tốc độ 95 nhịp mỗi phút (BPM) và sau đó đưa đám đông lên đến 140 BPM điên cuồng của kỹ thuật trance. Bạn sẽ kết thúc với sự kết hợp môi trường xung quanh 80 BPM êm dịu.
Bạn sẽ làm thế nào? Bạn phải kiểm soát nhịp và cần xây dựng công cụ để đưa bạn đến đó.

A Short History of Ambient & Downtempo by Mike G

Gặp gỡ Java DJ View

Hãy bắt đầu với View của công cụ. View cho phép bạn tạo nhịp trống và điều chỉnh lại nhịp mỗi phút …

Controller ở giữa…

Controller nằm giữa View Model. Nó nhận đầu vào (input) của bạn, chẳng hạn như chọn “Start” từ menu DJ Control và biến nó thành một hành động trên Model để bắt đầu tạo nhịp.

Đừng quên về Model ở bên dưới tất cả…

Bạn không thể nhìn thấy Model, nhưng bạn có thể “nghe thấy” nó. Model nằm bên dưới mọi thứ khác, quản lý nhịp và điều khiển loa bằng MIDI.

Đặt các phần lại với nhau

Xây dựng các phần

Được rồi, bạn biết Model chịu trách nhiệm duy trì tất cả dữ liệu, trạng thái và mọi logic ứng dụng. Vậy BeatModel có gì trong đó? Công việc chính của nó là quản lý nhịp, vì vậy nó có trạng thái duy trì nhịp hiện tại mỗi phút và rất nhiều Code tạo ra các sự kiện MIDI để tạo ra nhịp mà chúng ta nghe thấy. Nó cũng hiển thị một giao diện cho phép Controller thao tác nhịp và cho phép View Controller có được trạng thái của Model.
Ngoài ra, đừng quên rằng Model sử dụng Observer Pattern, vì vậy chúng ta cũng cần một số phương thức để cho phép các đối tượng đăng ký làm Observer và gửi thông báo.

Hãy xem BeatModelInterface trước khi xem cách triển khai:

Bây giờ chúng ta hãy xem xét lớp BeatModel cụ thể:

Mô hình này sử dụng hỗ trợ âm thanh MIDI của Java để tạo beat. Bạn có thể kiểm tra việc triển khai đầy đủ tất cả các lớp DJ trong tệp nguồn Java có sẵn trên trang headfirstlabs.com hoặc xem code ở cuối chương.

View

Bây giờ niềm vui bắt đầu; chúng ta có thể kết nối một View và hình dung ra BeatModel!
Điều đầu tiên cần lưu ý về View là chúng tôi đã triển khai View để nó được hiển thị trong hai cửa sổ riêng biệt. Một cửa sổ chứa BPM hiện tại; cái kia chứa các điều khiển giao diện. Tại sao ư? Chúng tôi muốn nhấn mạnh sự khác biệt giữa giao diện chứa View Model và phần còn lại của giao diện chứa tập hợp các điều khiển của người dùng. Chúng ta hãy xem xét kỹ hơn hai phần của View:

Sử dụng sức mạnh bộ não

BeatModel của chúng tôi không đưa ra giả định nào về lượt xem. Model được thực hiện bằng cách sử dụng Observer, vì vậy nó chỉ thông báo cho những View nào được đăng ký làm “người quan sát” khi trạng thái của nó thay đổi. View sử dụng API của Model để có quyền truy cập vào trạng thái. Chúng tôi đã triển khai một loại View, bạn có thể nghĩ đến các View khác có thể sử dụng các thông báo và trạng thái trong BeatModel không?

Ví dụ: Một buổi trình diễn ánh sáng dựa trên nhịp thời gian thực? Chế độ xem dạng text hiển thị thể loại nhạc dựa trên BPM (môi trường xung quanh, nhịp điệu, công nghệ, v.v.)

Triển khai View

Hai phần của dạng View – là View của Model và View với các điều khiển giao diện người dùng – được hiển thị trong hai cửa sổ, nhưng cùng tồn tại trong một lớp Java. Trước tiên, chúng tôi sẽ chỉ cho bạn thấy code tạo View của Model, hiển thị BPM hiện tại và thanh nhịp.
Sau đó, chúng tôi sẽ quay lại trang tiếp theo và chỉ hiển thị cho bạn code tạo ra các điều khiển giao diện người dùng, hiển thị trường nhập văn bản BPM và các button.

Đoạn code trên trang này chỉ là một phác thảo!

Những gì chúng tôi đã làm ở đây là chia MỘT lớp thành HAI, hiển thị cho bạn một phần của View trên trang này và phần khác trên trang tiếp theo. Tất cả code này thực sự nằm trong MỘT lớp – DJView.java. Tất cả được liệt kê ở cuối chương.

Tiếp tục triển khai View…

Bây giờ, chúng ta sẽ xem xét code cho phần control giao diện người dùng của View. View này cho phép bạn điều khiển Model bằng cách cho Controller biết phải làm gì, từ đó sẽ cho Model biết phải làm gì. Hãy nhớ rằng code này nằm trong cùng một tệp lớp với code View khác.

Bây giờ cho Controller

Đã đến lúc viết phần còn thiếu: Controller. Hãy nhớ rằng Controller là chiến lược (strategy) mà chúng tôi đưa vào View để cung cấp cho nó một số tính năng thông minh.
Bởi vì chúng tôi đang triển khai Mẫu chiến lược, chúng tôi cần bắt đầu với interface cho bất kỳ Strategy nào có thể được dùng vào DJ View. Chúng tôi sẽ gọi nó là ControllerInterface.

Bài tập: Bạn đã thấy rằng View Controller cùng sử dụng Mẫu chiến lược. Bạn có thể vẽ một sơ đồ lớp của hai đại diện cho mô hình này không?

Và đây là cách triển khai Controller:

Đặt tất cả lại với nhau

Chúng tôi có mọi thứ mình cần: Model, View Controller.
Bây giờ đã đến lúc tập hợp tất cả chúng lại thành một MVC! Chúng ta sẽ xem cách chúng làm việc cùng nhau hiệu quả như thế nào.
Tất cả những gì chúng ta cần là một đoạn code nhỏ để bắt đầu mọi thứ:

Kết quả

Những thứ đã làm

1. Bắt đầu tạo beat với menu Start; thông báo Controller disable menu này ngay sau đó.
2. Sử dụng mục nhập văn bản cùng với các nút tăng và giảm để thay đổi BPM. Lưu ý cách View phản ánh những thay đổi mặc dù thực tế là nó không có liên kết logic với các Controller.
3. Lưu ý cách “beat bar” luôn theo kịp beat vì nó là observer của Model.
4. Đặt bài hát yêu thích của bạn và xem liệu beat có tăng, giảm hay không bằng cách sử dụng các nút điều khiển tăng(>>) và giảm (<<).
5. Dừng phát. Lưu ý cách Controller disable menu Stop và enable menu Start.

Khám phá Strategy

Hãy cùng tìm hiểu Mẫu Strategy xa hơn một chút để hiểu rõ hơn về cách nó được sử dụng trong MVC. Chúng ta cũng sẽ thấy một mẫu thân thiện khác cũng xuất hiện – một mẫu bạn sẽ thường thấy xung quanh bộ ba MVC: Mẫu Adapter.
Hãy suy nghĩ một chút về những gì View DJ thực hiện: nó hiển thị tốc độ beat. Điều đó có giống như một cái gì đó khác không? Làm thế nào về một nhịp tim? Tình cờ là chúng tôi có một Class theo dõi tim; đây là sơ đồ lớp:

Sử dụng sức mạnh bộ não

Chắc chắn sẽ rất tuyệt nếu sử dụng lại View hiện tại của chúng tôi với HeartModel, nhưng chúng tôi cần một Controller hoạt động với Model này. Ngoài ra, giao diện của HeatModel không phù hợp với những gì mà View mong đợi vì nó có phương thức getHeartRate() chứ không phải là getBPM(). Bạn sẽ thiết kế một tập hợp các lớp như thế nào để cho phép View được sử dụng lại với Model mới?

Adapting the Model

Đối với người mới bắt đầu, chúng tôi sẽ cần phải điều chỉnh HeartModel thành BeatModel. Nếu chúng tôi không làm vậy, View sẽ không thể hoạt động với Model này, vì View chỉ biết cách getBPM() và phương thức tương đương là getHeartRate(). Chúng ta sẽ làm việc này như thế nào? Tất nhiên, chúng tôi sẽ sử dụng Mẫu Adapter! Nó chỉ ra rằng đây là một kỹ thuật phổ biến khi làm việc với MVC: sử dụng một Adapter để điều chỉnh một Model để làm việc với các ControllerView hiện có.
Đây là code để điều chỉnh HeartModel thành BeatModel:

Bây giờ chúng tôi đã sẵn sàng cho một HeartController

Với HeartAdapter trong tay, chúng ta nên sẵn sàng tạo Controller và chạy View với HeartModel. Nói về tái sử dụng!

Và thế là xong! Bây giờ là lúc cho một số code thử nghiệm …

Và bây giờ để chạy thử …

Những thứ đã làm

Lưu ý rằng màn hình hoạt động tuyệt vời với một heart! Beat trông giống như một nhịp đập. Vì HeartModel cũng hỗ trợ BPM và Beat Observer, nên chúng tôi có thể nhận cập nhật nhịp giống như với nhịp của DJ.
Vì heartbeat có sự thay đổi tự nhiên, hãy lưu ý rằng màn hình được cập nhật với beat mới mỗi phút.
Mỗi khi chúng tôi nhận được bản cập nhật BPM, adapter sẽ thực hiện công việc dịch các lệnh gọi getBPM() sang các lệnh gọi getHeartRate().
Các mục menu Start Stop không được hiện vì Controller đã disable chúng.
Các nút khác vẫn hoạt động nhưng không có tác dụng vì Controller không thực hiện các hoạt động nào cho chúng.
View có thể được thay đổi để hỗ trợ việc tắt các mục này.

MVC và Web

Không lâu sau khi Web được ra đời, các nhà phát triển bắt đầu điều chỉnh MVC để phù hợp với mô hình “trình duyệt – máy chủ”. Sự thích ứng hiện hành được gọi đơn giản là “Model 2” và sử dụng sự kết hợp của công nghệ servlet và JSP để đạt được sự tách biệt giữa Model, ViewController mà chúng ta thấy trong GUI thông thường.
Hãy xem cách Model 2 hoạt động:

1. Bạn thực hiện một yêu cầu HTTP, được nhận bởi một servlet

Sử dụng trình duyệt web của bạn, bạn thực hiện một yêu cầu HTTP. Điều này thường liên quan đến việc gửi một số dữ liệu (form data), như tên người dùng và mật khẩu của bạn. Một servlet nhận dữ liệu này và phân tích cú pháp nó.

2. Servlet hoạt động như Controller.

Servlet đóng vai trò của Controller và xử lý yêu cầu của bạn, rất có thể đưa ra các yêu cầu tới Model (thường là cơ sở dữ liệu). Kết quả của việc xử lý yêu cầu thường được đóng gói dưới dạng JavaBean.

3. Controller chuyển tiếp tới View.

View được đại diện bởi một JSP. Công việc duy nhất của JSP là tạo trang đại diện cho View của Model (4. thứ mà nó lấy được thông qua JavaBean) cùng với bất kỳ xử lý nào cần thiết cho các hành động tiếp theo.

5. View trả về một trang cho trình duyệt qua HTTP.

Một trang được trả về trình duyệt, nơi nó được hiển thị dưới dạng View. Khi người dùng gửi các yêu cầu khác, được xử lý theo cùng một kiểu.

Model 2: không chỉ là một thiết kế sạch sẽ.

Lợi ích của việc tách View, ModelController đã khá rõ ràng đối với bạn. Nhưng bạn cần biết “phần còn lại của câu chuyện” với Model 2 – rằng nó đã cứu nhiều trang web khỏi bị chìm vào mớ hỗn loạn.
Làm sao? Vâng, Model 2 không chỉ cung cấp sự tách biệt giữa các thành phần về mặt thiết kế, nó còn cung cấp sự tách biệt trong “trách nhiệm sản xuất”. Hãy đối mặt với điều đó, ngày xưa, bất kỳ ai có quyền truy cập vào JSP của bạn đều có thể truy cập và viết bất kỳ đoạn code Java nào họ muốn, phải không? Và điều đó bao gồm rất nhiều người không biết tệp .jar từ một tập hợp tệp .jar. Thực tế là hầu hết các nhà sản xuất web đều biết về nội dung và HTML, chứ không phải phần mềm.
May mắn là Model 2 đã đến giải cứu. Với Model 2, chúng tôi có thể để các công việc của developer cho những chàng trai và cô gái biết Servlet và để các nhà sản xuất web tự do với các JSP kiểu Model 2 đơn giản, nơi tất cả các nhà sản xuất có quyền truy cập là HTML và JavaBeans đơn giản.

Model 2: DJ từ điện thoại di động

Bạn không nghĩ rằng chúng tôi sẽ cố gắng bỏ qua mà không chuyển BeatModel tuyệt vời đó sang Web phải không? Hãy nghĩ rằng, bạn có thể kiểm soát toàn bộ phiên DJ của mình thông qua một trang web trên điện thoại di động của bạn. Vì vậy, bây giờ bạn có thể ra khỏi điều khiển DJ và hòa mình vào đám đông. Bạn còn chờ gì nữa? Hãy viết đoạn code đó!

Kế hoạch:

1. Sửa model

Thực ra thì, chúng ta không phải sửa Model, cứ như vậy là đã ổn!

2. Tạo servlet controller

Chúng tôi cần một servlet đơn giản có thể nhận các yêu cầu HTTP của chúng tôi và thực hiện một vài thao tác lên model. Tất cả những gì nó cần làm là Stop, Start và thay đổi nhịp mỗi phút.

3. Tạo HTML view

Chúng tôi sẽ tạo một View đơn giản với JSP. Nó sẽ nhận được một JavaBean từ Controller sẽ cho nó biết mọi thứ nó cần để hiển thị. JSP sau đó sẽ tạo ra một giao diện HTML.

Thiết lập môi trường Servlet của bạn

Hướng dẫn bạn cách thiết lập môi trường servlet của bạn hơi lạc đề đối với một cuốn sách về Mẫu thiết kế, ít nhất là nếu bạn không muốn cuốn sách nặng hơn!
Khởi động trình duyệt web của bạn và truy cập thẳng vào http://jakarta.apache.org/tomcat/ cho Apache Jakarta Project’s Tomcat Servlet Container. Bạn sẽ tìm thấy mọi thứ bạn cần ở đó để giúp bạn thiết lập và hoạt động.
Bạn cũng sẽ muốn xem Head First Servlets & JSP của Bryan Basham, Kathy Sierra và Bert Bates.

Bước một: Model

Hãy nhớ rằng trong MVC, model không biết bất kỳ điều gì về View hoặc Controller. Nói cách khác, nó hoàn toàn được tách rời. Tất cả những gì nó biết là nó có thể có những người quan sát (observer) mà nó cần thông báo. Nó cũng cung cấp một giao diện mà các ViewController có thể sử dụng để lấy và thiết lập trạng thái của nó.
Bây giờ, tất cả những gì chúng ta cần làm là điều chỉnh nó để hoạt động trong môi trường web, nhưng, do nó không phụ thuộc vào bất kỳ lớp bên ngoài nào, nên thực sự không có việc gì phải làm. Chúng tôi có thể sử dụng BeatModel của mình mà không cần thay đổi. Vì vậy, hãy chuyển sang bước hai!

Bước hai: controller servlet

Hãy nhớ rằng, servlet sẽ hoạt động như Controller của chúng ta; nó sẽ nhận đầu vào của trình duyệt Web trong một yêu cầu HTTP và chuyển nó thành các hành động có thể được áp dụng cho Model.
Sau đó, với cách thức hoạt động của Web, chúng ta cần return một View cho trình duyệt. Để làm điều này, chúng tôi sẽ chuyển quyền kiểm soát cho View (có dạng JSP). Chúng ta sẽ làm điều này trong bước ba.
Đây là phác thảo của servlet; trên trang tiếp theo, chúng tôi sẽ xem xét việc triển khai đầy đủ.

Đây là cách triển khai phương thức doGet():

Bây giờ chúng ta cần 1 View

Tất cả những gì chúng tôi cần là một cái nhìn và chúng tôi đã có trình tạo nhịp dựa trên trình duyệt của mình sẵn sàng hoạt động!
Trong Model 2, View chỉ là một JSP. Tất cả những gì JSP biết là bean mà nó nhận được từ Controller. Trong trường hợp của chúng ta, bean đó chỉ là mô hình và JSP sẽ chỉ sử dụng thuộc tính BPM của nó để trích xuất các nhịp hiện tại mỗi phút. Với dữ liệu đó trong tay, nó tạo ra View và cũng như các điều khiển giao diện người dùng.

Test Model 2

Đã đến lúc khởi động trình duyệt web của bạn, nhấn DJView Servlet và cho hệ thống quay …

Những thứ đã làm

  1. Đầu tiên, hãy truy cập vào trang web; bạn sẽ thấy nhịp mỗi phút ở mức 0. Hãy tiếp tục và nhấp vào nút “On”.
  2. Bây giờ bạn sẽ thấy nhịp mỗi phút ở cài đặt mặc định: 90 BPM. Bạn cũng sẽ nghe thấy nhịp trên máy mà máy chủ đang chạy.
  3. Nhập một beat cụ thể, chẳng hạn, 120, và nhấp vào nút “set”. Trang sẽ được làm mới với nhịp mỗi phút là 120 (và bạn sẽ nghe thấy nhịp tăng lên).
  4. Bây giờ chơi với các nút tăng / giảm để điều chỉnh nhịp lên và xuống.
  5. Suy nghĩ về cách hoạt động của từng bước trong hệ thống. Giao diện HTML thực hiện một yêu cầu tới servlet (Controller); servlet phân tích cú pháp đầu vào của người dùng và sau đó đưa ra các yêu cầu đối với model. Sau đó, servlet chuyển quyền điều khiển đến JSP (View), tạo ra View HTML được trả về và hiển thị.

Design pattern và Model 2

Sau khi triển khai DJ control cho Web bằng Model 2, bạn có thể tự hỏi các Pattern đã đi đâu. Chúng tôi có một View được tạo trong HTML từ một JSP nhưng View không còn là một trình lắng nghe của Model. Chúng tôi có một Controller là một servlet nhận các yêu cầu HTTP, nhưng chúng vẫn đang sử dụng Strategy pattern? Còn Composite thì sao? Chúng tôi có một View được tạo từ HTML và hiển thị trong trình duyệt web. Đó có còn là Composite pattern không?

Model 2 là một bản chuyển thể của MVC sang Web

Mặc dù Model 2 trông không giống hệt MVC “sách giáo khoa”, tất cả các phần vẫn ở đó; chúng vừa được điều chỉnh để loại bỏ các đặc điểm riêng của mô hình trình duyệt web. Hãy xem xét lại…

Observer

View không còn là người quan sát model theo nghĩa cổ điển; nghĩa là nó không đăng ký với Model để nhận thông báo thay đổi trạng thái.

Tuy nhiên, View nhận được tương đương với các thông báo gián tiếp từ Controller khi model đã được thay đổi. Controller thậm chí chuyển View một bean cho phép View truy xuất trạng thái của model.

Nếu bạn nghĩ về model trình duyệt, View chỉ cần cập nhật thông tin trạng thái khi phản hồi HTTP được trả về trình duyệt; thông báo vào bất kỳ thời điểm nào khác sẽ là vô nghĩa. Chỉ khi một trang đang được tạo và trả về thì việc tạo View và kết hợp trạng thái của model mới có ý nghĩa.

Strategy

Trong Model 2, Strategy object vẫn là servlet Controller; tuy nhiên, nó không được tạo trực tiếp với View theo cách cổ điển. Điều đó nói rằng, nó là một đối tượng thực hiện hành vi cho View và chúng ta có thể hoán đổi nó cho một Controller khác nếu chúng ta muốn hành vi khác.

Composite

Giống như Swing GUI của chúng tôi, View cuối cùng được tạo thành từ một tập hợp các thành phần đồ họa lồng với nhau. Trong trường hợp này, chúng được trình duyệt web hiển thị bằng HTML, tuy nhiên bên dưới có một hệ thống đối tượng rất có thể tạo thành một composite.

Không có câu hỏi ngớ ngẩn

Hỏi: Mẫu Composite thực sự có trong MVC không?
Đáp: Vâng, thực sự có một Composite pattern trong MVC. Nhưng, thực ra, đây là một câu hỏi rất hay. Ngày nay, các gói GUI, như Swing, đã trở nên phức tạp đến mức chúng ta hầu như không nhận thấy cấu trúc bên trong và việc sử dụng composite trong việc xây dựng và cập nhật màn hình. Điều đó thậm chí còn khó thấy hơn khi chúng ta có các trình duyệt Web có thể sử dụng ngôn ngữ đánh dấu (markup language) và chuyển đổi nó thành giao diện người dùng. Trở lại khi MVC lần đầu tiên được phát hiện, việc tạo GUI đòi hỏi nhiều can thiệp thủ công hơn và rõ ràng composite pattern là một phần của MVC.

Hỏi: Controller có bao giờ thực hiện bất kỳ logic ứng dụng nào không?
Đáp: Không, Controller thực hiện hành vi cho View. Nó rất thông minh khi chuyển các hành động từ View thành các hành động trên model. Model thực hiện các hành động đó và thực hiện logic ứng dụng để quyết định phải làm gì để đáp lại các hành động đó. Controller có thể phải thực hiện một số công việc nhỏ để xác định phương thức gọi nào cần thực hiện trên model, nhưng đó không được coi là “logic ứng dụng”. Logic ứng dụng là code quản lý và thao tác dữ liệu của bạn và nó nằm trong Model.

Hỏi: Tôi luôn thấy từ “model” khó có thể hiểu được trong đầu. Bây giờ tôi hiểu rằng đó là phần lõi của ứng dụng, nhưng tại sao một từ mơ hồ, khó hiểu như vậy lại được sử dụng để mô tả khía cạnh này của MVC?
Đáp: Khi MVC được đặt tên, họ cần một từ bắt đầu bằng chữ “M”, nếu không họ không thể gọi nó là MVC. Nhưng nghiêm túc mà nói, chúng tôi đồng ý với bạn, mọi người đều vò đầu bứt tai tự hỏi thế nào là model. Nhưng sau đó mọi người nhận ra rằng họ cũng không thể nghĩ ra từ nào hay hơn.

Hỏi: Bạn đã nói rất nhiều về trạng thái của Model. Điều này có nghĩa là nó có State Pattern trong đó?
Đáp: Không, chúng tôi chỉ muốn nói đến ý tưởng chung về trạng thái. Nhưng chắc chắn một số model sử dụng State Pattern để quản lý các trạng thái bên trong của chúng.

Hỏi: Tôi đã xem các mô tả về MVC trong đó Controller được mô tả như một “thành phần trung gian” giữa View và Model. Controller có triển khai Mediator Pattern không?
Đáp: Chúng tôi chưa đề cập đến Mediator Pattern, vì vậy chúng tôi sẽ không đi sâu vào quá nhiều chi tiết ở đây, nhưng mục đích của Mediator Pattern là gói gọn cách các đối tượng tương tác và thúc đẩy kết hợp lỏng lẻo bằng cách giữ cho hai đối tượng không tham chiếu đến nhau một cách rõ ràng. Vì vậy, ở một mức độ nào đó, Controller có thể được xem như một mediator, vì View không bao giờ đặt trạng thái trực tiếp trên Model, mà luôn đi qua Controller. Tuy nhiên, hãy nhớ rằng View có tham chiếu đến Model để truy cập trạng thái của nó. Nếu Controller thực sự là một mediator, View sẽ phải đi qua Controller để có được trạng thái của Model.

Hỏi: View luôn phải yêu cầu trạng thái của Model? Tại sao chúng tôi dùng Model để gửi trạng thái của nó cùng với thông báo cập nhật?
Đáp: Có, model chắc chắn có thể gửi trạng thái của nó cùng với thông báo và trên thực tế, nếu bạn nhìn lại View JSP / HTML, đó chính xác là những gì chúng tôi đang làm. Chúng tôi đang gửi toàn bộ model trong bean, mà View sử dụng để truy cập trạng thái nó cần bằng cách sử dụng các thuộc tính bean. Chúng tôi có thể làm điều gì đó tương tự với BeatModel bằng cách chỉ gửi trạng thái mà View quan tâm. Tuy nhiên, nếu bạn nhớ về chương Observer pattern, bạn cũng sẽ nhớ rằng điều này có một vài nhược điểm.

Hỏi: Nếu tôi có nhiều hơn một View, tôi có luôn cần nhiều hơn một Controller không?
Đáp: Thông thường, bạn cần một Controller cho mỗi View trong thời gian chạy; tuy nhiên, cùng một lớp Controller có thể dễ dàng quản lý nhiều View.

Hỏi: View không được phép thao tác Model, tuy nhiên, tôi nhận thấy trong quá trình triển khai của bạn rằng View có toàn quyền truy cập vào các phương thức thay đổi trạng thái của Model. Điều này có nguy hiểm không?
Đáp: Bạn đúng; chúng tôi đã cấp cho View toàn quyền truy cập vào bộ phương thức của model. Chúng tôi đã làm điều này để đơn giản hóa mọi thứ, nhưng có thể có những trường hợp bạn muốn cấp cho View quyền truy cập chỉ vào một phần API của model của bạn. Có một mẫu thiết kế tuyệt vời cho phép bạn điều chỉnh giao diện để chỉ cung cấp một tập hợp con. Bạn có biết đó là mẫu nào chưa?

Tóm tắt

  • Mẫu Model-View-Controller (MVC) là một mẫu phức hợp bao gồm các mẫu Observer, Strategy và Composite.
  • Model sử dụng Mẫu Observer để có thể cập nhật những người quan sát nhưng vẫn tách rời khỏi chúng.
  • Controller là strategy cho View. View có thể sử dụng các triển khai khác nhau của Controller để có được các hành vi khác nhau.
  • View sử dụng Composite để triển khai giao diện người dùng, giao diện này thường bao gồm các thành phần lồng nhau như panel, frame và button.
  • Các mẫu này phối hợp với nhau để tách ba vai trò trong mô hình MVC, giúp thiết kế luôn rõ ràng và linh hoạt.
  • Mẫu Adapter Pattern có thể được sử dụng để điều chỉnh một Model mới với View Controller hiện có.
  • Model 2 là một bản chuyển thể của MVC cho các ứng dụng web.
  • Trong Model 2, Controller được triển khai như một servlet và JSP & HTML triển khai View.

2 nhận xét về “Chương 12: Kết hợp design pattern – MVC Pattern – Mẫu của các mẫu (P2)”

  1. Thank bro .không biết seri này còn nữa k bro bánh cuốn quá . chúc bro tiếp tục giữ lửa

    1. Seri cuốn sách này thì đã hết. Hiện tại là seri Clean Code, đến khi hết thì sẽ quay lại 1 seri design pattern khác nhé. Mong bạn tiếp tục ủng hộ.

Trả lời

Email của bạn sẽ không được hiển thị công khai.