Factory Pattern – Nhà máy của những đối tượng

Công Nghệ
Factory Pattern – Nhà máy của những đối tượng
Bài viết được sự cho phép của tác giả Edward Thien Hoang FACTORY PATTERN Chào mọi người, hôm nay mình sẽ tiếp tục loạt bài về Design Pattern với một pattern mới: Factory Pattern. Pattern này sẽ giúp chúng ta có một hướng giải quyết đúng đắn khi đối mặt với việc phải dùng những lệnh if/else trong khối xử lý để tạo ra những đối tượng khác nhau dựa vào điều kiện ban đầu cho trước . Factory Function vs. Class Factory Method trong thực tiễn KHI KHÔNG CÓ NHÀ MÁY Chúng ta bắt đầu câu chuyện tại một công ty IT có tên AZ Company cùng với kiến trúc sư có tuổi nhưng chưa có tên A11 . Lúc này A11 đang đảm nhận dự án xây dựng 1 hệ thống có tên là “Course Management System” (CMS) để quản lý các khóa học trực tuyến. Cùng xem A11 sẽ làm thế nào để xây dựng hệ thống này, anh ta am hiểu khá rõ về các khái niệm trong lập trình hướng đối tượng như kế thừa và đa hình, vậy là thiết kế ban đầu ra đời ngay sau đó mà không mất quá nhiều suy nghĩ. public class CourseController { public static String COURSE_JAVA = "Java" ; public static String COURSE_DOT_NET = ".NET" ; public void displayCourse(String inCourseName) { AbstractCourse course = null ; if (inCourseName.equals(COURSE_JAVA)) { course = new JavaCourse(); } else if (inCourseName.equals(COURSE_DOT_NET)) { course = new DotNetCourse(); } if (course != null ) { course.display(); } else { System.out.println( "Nothing is displayed" ); } } } public class FactoryTest { public static void main(String[] args) { CourseController controller = new CourseController(); controller.displayCourse(CourseController.COURSE_DOT_NET); } } Hệ thống của A11 được đưa vào vận hành và không gặp bất kỳ vấn đề gì và...

Bài viết được sự cho phép của tác giả Edward Thien Hoang

FACTORY PATTERN

Chào mọi người, hôm nay mình sẽ tiếp tục loạt bài về Design Pattern với một pattern mới: Factory Pattern. Pattern này sẽ giúp chúng ta có một hướng giải quyết đúng đắn khi đối mặt với việc phải dùng những lệnh if/else trong khối xử lý để tạo ra những đối tượng khác nhau dựa vào điều kiện ban đầu cho trước.

KHI KHÔNG CÓ NHÀ MÁY

Chúng ta bắt đầu câu chuyện tại một công ty IT có tên AZ Company cùng với kiến trúc sư có tuổi nhưng chưa có tên A11. Lúc này A11 đang đảm nhận dự án xây dựng 1 hệ thống có tên là “Course Management System” (CMS) để quản lý các khóa học trực tuyến. Cùng xem A11 sẽ làm thế nào để xây dựng hệ thống này, anh ta am hiểu khá rõ về các khái niệm trong lập trình hướng đối tượng như kế thừa và đa hình, vậy là thiết kế ban đầu ra đời ngay sau đó mà không mất quá nhiều suy nghĩ.
Factory_1Factory_1

public class CourseController {     public static String COURSE_JAVA = "Java";     public static String COURSE_DOT_NET = ".NET";     public void displayCourse(String inCourseName) {         AbstractCourse course = null;         if(inCourseName.equals(COURSE_JAVA)) {             course = new JavaCourse();         }         else if(inCourseName.equals(COURSE_DOT_NET)) {             course = new DotNetCourse();         }         if(course != null) {             course.display();         }         else {             System.out.println("Nothing is displayed");         }     } } public class FactoryTest {     public static void main(String[] args) {         CourseController controller = new CourseController();         controller.displayCourse(CourseController.COURSE_DOT_NET);     } }

Hệ thống của A11 được đưa vào vận hành và không gặp bất kỳ vấn đề gì và mang lại lợi nhuận khá lớn cho công ty từ những khóa học online. Lúc này sếp của A11 muốn mở thêm một khóa học C/C++. A11 bắt đầu suy nghĩ và anh ta định sẽ vào lớp Controller để thêm 1 dòng if dành cho COURSE_C_PLUS_PLUS. Nhưng ý định đó dừng lại khi anh nghĩ đến việc sếp sẽ mở thêm hàng chục khóa học online khác, và chi phí để anh thay đổi cả lớp CourseController để đáp ứng lại là quá lớn. A11 nghĩ đến nguyên lý SOLID principle OCP (Open Closed Principle) và thấy mình đã vi phạm nó. Một hệ thống luôn phải được thay đổi theo thời gian và phải có cách nào đó để có thể đáp ứng được những thay đổi mà không phải sửa code (thật ra là sửa 1 chút, nhưng sửa đúng chỗ cần sửa). Bạn không thể nào giải phẫu nguyên một chiếc xe chỉ để vá cái bánh xe.

BẮT ĐẦU XÂY DỰNG MỘT NHÀ MÁY ĐƠN GIẢN

Câu chuyện sẽ tiếp tục, do đã học được từ những nguyên lý về thiết kế hướng đối tượng, ngày hôm sau, A11 đã quyết định sẽ tách biệt những phần thay đổi ra khỏi những phần ít bị thay đổi. Cụ thể ở đây là những đoạn if/else để khởi tạo những khóa học sẽ được thay thế bằng 1 “nhà máy” để khởi tạo những đối tượng đó một cách độc lập từ bên ngoài, kết quả của việc khởi tạo sẽ được đưa vào để xử lý cho những đoạn code phía sau.

Nhà máy đơn giản của A11:
Factory_2Factory_2

public class CourseFactory {
public static AbstractCourse createCourse(String inCourseName) {
AbstractCourse course = null;
if(inCourseName.equals(CourseController.COURSE_JAVA)) {
course = new JavaCourse();
}
else if(inCourseName.equals(CourseController.COURSE_DOT_NET)) {
course = new DotNetCourse();
}
return course;
}
}

public class CourseController {
public static String COURSE_JAVA = "Java";
public static String COURSE_DOT_NET = ".NET";
public void displayCourse(String inCourseName) {
AbstractCourse course = CourseFactory.createCourse(inCourseName);
if(course != null) {
course.display();
}
else {
System.out.println("Nothing is displayed");
}
}
}

Như đã thấy, phần mong manh dễ thay đổi nhất đã bị đưa ra một chỗ khác. A11 có thể tạm quên đi lớp CourseController mỗi khi có yêu cầu thêm mới 1 khóa học mới. Anh ta có thể ngủ ngon cho đến hết đêm nay và đêm mai nữa, ít ra là như vậy.

NHÀ MÁY BỊ QUÁ TẢI

Bây giờ công ty AZ đã thực sự lớn mạnh, bằng việc cung cấp các khóa học online, ngày càng có nhiều học viên đăng ký. Và trong số đó, có một số người đã không hài lòng với các khóa học online kiểu như vậy, họ muốn được học những khóa học offline, khi đó những câu hỏi sẽ được giải đáp nhanh hơn và hiệu quả hơn bằng cách tương tác trực tiếp với các giảng viên. Giám đốc công ty thấy được điều đó, đã mời thêm 1 số giáo sư về và bắt đầu cho học viên đăng ký những khóa học offline. Và tất nhiên A11 cũng có việc làm. Anh phải tiếp tục xây dựng những khóa học offline như vậy để thêm vào hệ thống.

Bây giờ hệ thống của A11 sẽ phải quản lý các khóa học như JavaOnlineCourse, DotNetOnlineCourse, CPlusPlusOnlineCourse, PHPOnlineCourse, JavaOfflineCourse, DotNetOfflineCourse, …

A11 sẽ thêm những khóa học Offline vào như hệ thống như thế nào? Anh suy nghĩ và câu trả lời chính là lớp CourseFactory. Anh sẽ thêm các điều kiện if/else vào để tạo ra những khóa học offline giống như việc anh làm với các khóa học online.

public class CourseFactory {
public static AbstractCourse createCourse(String inCourseName) {
AbstractCourse course = null;
if(inCourseName.equals(CourseController.COURSE_JAVA_ONLINE)) {
course = new JavaOnlineCourse();
}
else if(inCourseName.equals(CourseController.COURSE_DOT_NET_ONLINE)) {
course = new DotNetOnlineCourse();
}
else if(inCourseName.equals(CourseController.COURSE_JAVA_OFFLINE)) {
course = new JavaOfflineCourse();
}
else if(inCourseName.equals(CourseController.COURSE_DOT_NET_OFFLINE)) {
course = new DotNetOfflineCourse();
}
return course;
}
}

Hệ thống vẫn vận hành tốt. Mỗi khi có một khóa học online được mở ra, A11 sẽ vào CourseFactory để sửa, mỗi khi có một khóa học Offline mở ra, A11 cũng sẽ vào CourseFactory để sửa. Và mỗi khi có một loại hình khóa học mới được mở ra, lớp CourseFactory cũng sẽ được để ý đến… Phải chẳng CourseFactory bây giờ lại đang gặp vấn đề tương tự với CourseController ban đầu? Nó cũng bị ảnh hưởng nhiều mỗi khi có một yêu cầu mới (một loại hình khóa học mới). Nhắc lại nguyên lý SOLID Principle SRP – Single Responsibility Principle, mỗi lớp chỉ có một và duy nhất một lý do để thay đổi. Vậy thì hãy làm cho CourseFactory chỉ có một lý do duy nhất để thay đổi bằng cách tách rời những thành phần logic khác nhau trong một lớp ra những thành phần nhỏ hơn bằng những lớp khác. Lúc này A11 lại nghĩ ra một phương án mới đó là mỗi loại hình khóa học sẽ có một “nhà máy” cho riêng nó. Vì vậy trong thiết kế hiện tại sẽ có 2 nhà máy: OnlineFactory và OfflineFactory.

XÂY DỰNG NHIỀU NHÀ MÁY

Thiết kế mới cho hệ thống multi-factory:
Factory_3Factory_3

public class OfflineCourseFactory {
public static AbstractCourse createCourse(String inCourseName) {
AbstractCourse course = null;
if(inCourseName.equals(CourseController.COURSE_JAVA_OFFLINE)) {
course = new JavaOfflineCourse();
}
else if(inCourseName.equals(CourseController.COURSE_DOT_NET_OFFLINE)) {
course = new DotNetOfflineCourse();
}
return course;
}
}

public class OnlineCourseFactory {
public static AbstractCourse createCourse(String inCourseName) {
AbstractCourse course = null;
if(inCourseName.equals(CourseController.COURSE_JAVA_ONLINE)) {
course = new JavaOnlineCourse();
}
else if(inCourseName.equals(CourseController.COURSE_DOT_NET_ONLINE)) {
course = new DotNetOnlineCourse();
}
return course;
}
}

Chúng ta biết rõ, để đăng ký 1 khóa học online thì chỉ cần đoạn code sau:

AbstractCourse onlineCourse = OnlineCourseFactory.createCourse(CourseController.COURSE_JAVA_ONLINE);

Và đây là đoạn code để đăng ký 1 khóa học offline:

AbstractCourse offlineCourse = OfflineCourseFactory.createCourse(CourseController.COURSE_DOT_NET_OFFLINE);

ĐƯA NHIỀU NHÀ MÁY VÀO SỬ DỤNG

Vấn đề còn lại là tích hợp chúng vào lớp CourseController để tạo ra 1 khóa học theo yêu cầu và display thông tin lên màn hình??? Ngay bây giờ, mình không thể nghĩ ra cách nào để có thể có thể tạo ra 1 khóa học tại hàm displayCourse. Thứ nhất, tại đây, ConurseController không thể quyết định được là sẽ tạo ra 1 khóa học online hay 1 khóa học offline bởi vì OnlineCourseFactory và OfflineCourseFactory là 2 lớp tách biệt. Có thể là chúng ta cần một tham số nữa trong hàm displayCourse để quyết định xem nên tạo loại hình khóa học nào. Lúc đó displayCourse sẽ thành:

public void displayCourse(String inCourseType, String inCourseName) {
AbstractCourse course = null;
if(inCourseType.equals(COURSE_TYPE_ONLINE)) {
course = OnlineCourseFactory.createCourse(inCourseName);
}
else if(inCourseType.equals(COURSE_TYPE_OFFLINE)) {
course = OfflineCourseFactory.createCourse(inCourseName);
}
// else if(inCourseType.equals(...))
if(course != null) {
course.display();
}
else {
System.out.println("Nothing is displayed");
}
}

Bây giờ thì chúng ta lại quay về với bài toán if/else ở phía trên. Mỗi khi có một loại hình khóa học mới được thêm vào, chúng ta lại phải thêm 1 block if/else để tạo ra khóa học ứng với loại hình đó. Tại đây magic sẽ xuất hiện. Thử nghĩ xem nếu có một “nhà máy sản xuất nhà máy” thì thế nào nhỉ? Nghĩa là hãy thử trừu tượng hóa đối tượng Factory, do đó, lớp Controller sẽ không phải phụ thuộc vào các lớp nhà máy cụ thể như: OnlineCourseFactory và OfflineCourseFactory. Nếu các bạn đã đọc qua bài viết “Why extends is evil” hoặc các nguyên lý hướng đối tượng có thể hiểu được chỉ nên làm việc với các interface (abstract) chứ không phải là các lớp cụ thể. Vì vậy đừng ngần ngại mà abstract đối tượng nhà máy Factory.

XÂY DỰNG NHÀ MÁY CỦA NHỮNG NHÀ MÁY

Thiết kế mới cho các đối tượng Factory sẽ như sau:
Factory_4Factory_4

public abstract class AbstractCourseFactory {
public AbstractCourse createCourse(String inCourseName) {
AbstractCourse course = getCourse(inCourseName);
if(course != null) {
// Do a bunch of things here, such as initializing some information
// for the course before returning it to caller
}
return course;
}

public abstract AbstractCourse getCourse(String inCourseName);
}
public class OfflineCourseFactory extends AbstractCourseFactory {
public AbstractCourse getCourse(String inCourseName) {
AbstractCourse course = null;
if(inCourseName.equals(CourseController.COURSE_JAVA_OFFLINE)) {
course = new JavaOfflineCourse();
}
else if(inCourseName.equals(CourseController.COURSE_DOT_NET_OFFLINE)) {
course = new DotNetOfflineCourse();
}
return course;
}
}
public class OnlineCourseFactory extends AbstractCourseFactory {
public AbstractCourse getCourse(String inCourseName) {
AbstractCourse course = null;
if(inCourseName.equals(CourseController.COURSE_JAVA_ONLINE)) {
course = new JavaOnlineCourse();
}
else if(inCourseName.equals(CourseController.COURSE_DOT_NET_ONLINE)) {
course = new DotNetOnlineCourse();
}
return course;
}
}

(Chú ý là mình đã thay đổi phương thức createCourse thành non-static nhé)

QUANG CẢNH CUỐI CÙNG

OK, hãy tái cấu trúc lại lớp CourseController để có một thiết kế hoàn chỉnh
Factory_5Factory_5

Toàn bộ source chương trình sẽ như sau:

public class CourseConstants {
public static String COURSE_JAVA_ONLINE = "JavaOnline";
public static String COURSE_DOT_NET_ONLINE = ".NETOnline";
public static String COURSE_JAVA_OFFLINE = "JavaOffline";
public static String COURSE_DOT_NET_OFFLINE = ".NETOffline";
}

public abstract class AbstractCourse {
private String courseName;
private long courseDuration;
public abstract void display();
}

public class DotNetOfflineCourse extends AbstractCourse {
@Override
public void display() {
System.out.println("Information of .NET offline course");
}
}

public class DotNetOnlineCourse extends AbstractCourse {
@Override
public void display() {
System.out.println("Information of .NET online course");
}
}

public class JavaOfflineCourse extends AbstractCourse {
@Override
public void display() {
System.out.println("Information of Java offline course");
}
}

public class JavaOnlineCourse extends AbstractCourse {
@Override
public void display() {
System.out.println("Information of Java online course");
}
}

public abstract class AbstractCourseFactory {
public AbstractCourse createCourse(String inCourseName) {
AbstractCourse course = getCourse(inCourseName);
if(course != null) {
// Do a bunch of things here, such as initializing some information
// for the course before returning it to caller
}
return course;
}

protected abstract AbstractCourse getCourse(String inCourseName);
}

public class OfflineCourseFactory extends AbstractCourseFactory {
public AbstractCourse getCourse(String inCourseName) {
AbstractCourse course = null;
if(inCourseName.equals(CourseConstants.COURSE_JAVA_OFFLINE)) {
course = new JavaOfflineCourse();
}
else if(inCourseName.equals(CourseConstants.COURSE_DOT_NET_OFFLINE)) {
course = new DotNetOfflineCourse();
}
return course;
}
}

public class OnlineCourseFactory extends AbstractCourseFactory {
public AbstractCourse getCourse(String inCourseName) {
AbstractCourse course = null;
if(inCourseName.equals(CourseConstants.COURSE_JAVA_ONLINE)) {
course = new JavaOnlineCourse();
}
else if(inCourseName.equals(CourseConstants.COURSE_DOT_NET_ONLINE)) {
course = new DotNetOnlineCourse();
}
return course;
}
}

public abstract class CourseController {
public void displayCourse(String inCourseName) {
AbstractCourse course = null;
AbstractCourseFactory factory = getCourseFactory();
course = factory.createCourse(inCourseName);
if(course != null) {
course.display();
}
else {
System.out.println("Nothing is displayed");
}
}
protected abstract AbstractCourseFactory getCourseFactory();
}

public class OfflineCourseController extends CourseController {
@Override
protected AbstractCourseFactory getCourseFactory() {
return new OfflineCourseFactory();
}
}

public class OnlineCourseController extends CourseController {
@Override
protected AbstractCourseFactory getCourseFactory() {
return new OnlineCourseFactory();
}
}

public class FactoryTest {
public static void main(String[] args) {
CourseController onlineController = new OnlineCourseController();
onlineController.displayCourse(CourseConstants.COURSE_DOT_NET_ONLINE);

CourseController offlineController = new OfflineCourseController();
offlineController.displayCourse(CourseConstants.COURSE_JAVA_OFFLINE);
}
}

Output:

Information of .NET online course
Information of Java offline course

Cùng nhìn lại toàn bộ những gì A11 đã làm từ những thiết kế ban đầu cho đến bây giờ. Từ việc chỉ quan tâm đến những khóa học được tao ra, anh ta tạo ra một thiết kế với kiểu kế thừa cha/con, và dùng if/else để tạo ra khóa học và display lên màn hình ứng với lựa chọn của người dùng. Sau đó, khi ngày càng có nhiều khóa học được thêm vào, A11 đã nghĩ ra cách phải loại bỏ những lệnh if/else ra khối xử lý chính, và FactoryMethod pattern được áp dụng để xử lý việc này bằng cách tạo ra lớp CourseFactory để “sinh” ra các khóa học theo yêu cầu, điều này đáp ứng được nguyên lý Open Closed Principle. Khi mà ngày càng có nhiều loại hình khóa học khác được thêm vào như Online, Offline, Corporate, … thì việc phải thay đổi lớp CourseFactory ngày càng thường xuyên hơn. Dẫn đến việc nguyên lý Single Responsibility Principle bị phá vỡ. AbstractFactory chính là hướng giải quyết trong lúc này. AbstractFactory sẽ để cho mỗi nhà máy Factory cụ thể tự “sinh” ra những khóa học đúng với trách nhiệm của nhà máy đó. Và đó là tất cả để chúng ta có được thiết kế cuối cùng.

Mình sẽ kết thúc mẫu thiết kế FactoryPattern tại đây. Nên nhớ rằng FactoryPattern gồm 2 loại: FactoryMethod (một nhà máy đơn giản) và AbstractFactory (nhà máy của những nhà máy), tùy theo yêu cầu của hệ thống mà mỗi pattern sẽ được áp dụng.

Bài viết gốc được đăng tải tại edwardthienhoang.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên Station D

Bài viết liên quan

Bộ cài đặt Laravel Installer đã hỗ trợ tích hợp Jetstream

Bộ cài đặt Laravel Installer đã hỗ trợ tích hợp Jetstream

Bài viết được sự cho phép của tác giả Chung Nguyễn Hôm nay, nhóm Laravel đã phát hành một phiên bản chính mới của “ laravel/installer ” bao gồm hỗ trợ khởi động nhanh các dự án Jetstream. Với phiên bản mới này khi bạn chạy laravel new project-name , bạn sẽ nhận được các tùy chọn Jetstream. Ví dụ: API Authentication trong Laravel-Vue SPA sử dụng Jwt-auth Cách sử dụng Laravel với Socket.IO laravel new foo --jet --dev Sau đó, nó sẽ hỏi bạn thích stack Jetstream nào hơn: Which Jetstream stack do you prefer? [0] Livewire [1] inertia > livewire Will your application use teams? (yes/no) [no]: ... Nếu bạn đã cài bộ Laravel Installer, để nâng cấp lên phiên bản mới bạn chạy lệnh: composer global update Một số trường hợp cập nhật bị thất bại, bạn hãy thử, gỡ đi và cài đặt lại nha composer global remove laravel/installer composer global require laravel/installer Bài viết gốc được đăng tải tại chungnguyen.xyz Có thể bạn quan tâm: Cài đặt Laravel Làm thế nào để chạy Sql Server Installation Center sau khi đã cài đặt xong Sql Server? Quản lý các Laravel route gọn hơn và dễ dàng hơn Xem thêm Tuyển dụng lập trình Laravel hấp dẫn trên Station D

By stationd
Principle thiết kế của các sản phẩm nổi tiếng

Principle thiết kế của các sản phẩm nổi tiếng

Tác giả: Lưu Bình An Phù hợp cho các bạn thiết kế nào ko muốn làm code dạo, design dạo nữa, bạn muốn cái gì đó cao hơn ở tầng khái niệm Nếu lập trình chúng ta có các nguyên tắc chung khi viết code như KISS , DRY , thì trong thiết kế cũng có những nguyên tắc chính khi làm việc. Những nguyên tắc này sẽ là kim chỉ nam, nếu có tranh cãi giữa các member trong team, thì cứ đè nguyên tắc này ra mà giải quyết (nghe hơi có mùi cứng nhắc, mình thì thích tùy cơ ứng biến hơn) Tìm các vị trí tuyển dụng designer lương cao cho bạn Nguyên tắc thiết kế của GOV.UK Đây là danh sách của trang GOV.UK Bắt đầu với thứ user cần Làm ít hơn Thiết kế với dữ liệu Làm mọi thứ thật dễ dàng Lặp. Rồi lặp lại lần nữa Dành cho tất cả mọi người Hiểu ngữ cảnh hiện tại Làm dịch vụ digital, không phải làm website Nhất quán, nhưng không hòa tan (phải có chất riêng với thằng khác) Cởi mở, mọi thứ tốt hơn Bao trừu tượng luôn các bạn, trang Gov.uk này cũng có câu tổng quát rất hay Thiết kế tốt là thiết kế có thể sử dụng. Phục vụ cho nhiều đối tượng sử dụng, dễ đọc nhất nhất có thể. Nếu phải từ bỏ đẹp tinh tế – thì cứ bỏ luôn . Chúng ta tạo sản phẩm cho nhu cầu sử dụng, không phải cho người hâm mộ . Chúng ta thiết kế để cả nước sử dụng, không phải những người đã từng sử dụng web. Những người cần dịch vụ của chúng ta nhất là những người đang cảm thấy khó sử dụng dịch...

By stationd
Hiểu về trình duyệt – How browsers work

Hiểu về trình duyệt – How browsers work

Bài viết được sự cho phép của vntesters.com Khi nhìn từ bên ngoài, trình duyệt web giống như một ứng dụng hiển thị những thông tin và tài nguyên từ server lên màn hình người sử dụng, nhưng để làm được công việc hiển thị đó đòi hỏi trình duyệt phải xử lý rất nhiều thông tin và nhiều tầng phía bên dưới. Việc chúng ta (Developers, Testers) tìm hiểu càng sâu tầng bên dưới để nắm được nguyên tắc hoạt động và xử lý của trình duyệt sẽ rất hữu ích trong công việc viết code, sử dụng các tài nguyên cũng như kiểm thử ứng dụng của mình. Cách để npm packages chạy trong browser Câu hỏi phỏng vấn mẹo về React: Component hay element được render trong browser? Khi hiểu được cách thức hoạt động của trình duyệt chúng ta có thể trả lời được rất nhiều câu hỏi như: Tại sao cùng một trang web lại hiển thị khác nhau trên hai trình duyệt? Tại sao chức năng này đang chạy tốt trên trình duyệt Firefox nhưng qua trình duyệt khác lại bị lỗi? Làm sao để trang web hiển thị nội dung nhanh và tối ưu hơn một chút?… Hy vọng sau bài này sẽ giúp các bạn có một cái nhìn rõ hơn cũng như giúp ích được trong công việc hiện tại. 1. Cấu trúc của một trình duyệt Trước tiên chúng ta đi qua cấu trúc, thành phần chung và cơ bản nhất của một trình duyệt web hiện đại, nó sẽ gồm các thành phần (tầng) như sau: Thành phần nằm phía trên là những thành phần gần với tương tác của người dùng, càng phía dưới thì càng sâu và nặng về xử lý dữ liệu hơn tương tác. Nhiệm...

By stationd
Thị trường EdTech Vietnam- Nhiều tiềm năng nhưng còn bị bỏ ngỏ tại Việt Nam

Thị trường EdTech Vietnam- Nhiều tiềm năng nhưng còn bị bỏ ngỏ tại Việt Nam

Lĩnh vực EdTech (ứng dụng công nghệ vào các sản phẩm giáo dục) trên toàn cầu hiện nay đã tương đối phong phú với nhiều tên tuổi lớn phân phối đều trên các hạng mục như Broad Online Learning Platforms (nền tảng cung cấp khóa học online đại chúng – tiêu biểu như Coursera, Udemy, KhanAcademy,…) Learning Management Systems (hệ thống quản lý lớp học – tiêu biểu như Schoology, Edmodo, ClassDojo,…) Next-Gen Study Tools (công cụ hỗ trợ học tập – tiểu biểu như Kahoot!, Lumosity, Curriculet,…) Tech Learning (đào tạo công nghệ – tiêu biểu như Udacity, Codecademy, PluralSight,…), Enterprise Learning (đào tạo trong doanh nghiệp – tiêu biểu như Edcast, ExecOnline, Grovo,..),… Hiện nay thị trường EdTech tại Việt Nam đã đón nhận khoảng đầu tư khoảng 55 triệu đô cho lĩnh vực này nhiều đơn vị nước ngoài đang quan tâm mạnh đến thị trường này ngày càng nhiều hơn. Là một trong những xu hướng phát triển tốt, và có doanh nghiệp đã hoạt động khá lâu trong ngành nêu tại infographic như Topica, nhưng EdTech vẫn chỉ đang trong giai đoạn sơ khai tại Việt Nam. Tại Việt Nam, hệ sinh thái EdTech trong nước vẫn còn rất non trẻ và thiếu vắng nhiều tên tuổi trong các hạng mục như Enterprise Learning (mới chỉ có MANA), School Administration (hệ thống quản lý trường học) hay Search (tìm kiếm, so sánh trường và khóa học),… Với chỉ dưới 5% số dân công sở có sử dụng một trong các dịch vụ giáo dục online, EdTech cho thấy vẫn còn một thị trường rộng lớn đang chờ được khai phá. *** Vừa qua Station D đã công bố Báo cáo Vietnam IT Landscape 2019 đem đến cái nhìn toàn cảnh về các ứng dụng công...

By stationd