Structural Pattern: Facade
This post hasn't been updated for 5 years
Facade là 1 parttern thuộc Structural Pattern, nó cung cấp 1 interface cho chung cho thay cho 1 nhóm interface có trong hệ thống con(subsystem), facade cung cấp interface ở mức độ cao hơn để người dùng có thể dễ dàng giao tiếp với 1 interface duy nhất, che dấu các xử lý phức tạp trong nó.
Việc sử dụng facade pattern có lợi ích sau:
- Giúp cho thư viện của bạn trở nên đơn giản hơn trong việc hiểu nó, vì mỗi facade sẽ đại diện cho 1 task vụ chung
- Giúp code dễ đọc hơn
- Gỉam việc phục thuộc code bên ngoài với hệ thống
- Đóng gói nhiều api thành 1 api được thiết kế tốt hơn
- Che đi phần phức tạp của subsystem với bên ngoài
Dưới đây là mô hình cấu trúc facade
Sau đây là ví dụ về việc sử dụng facade Trong bài toán người lùn đi đào vàng, ở phía client thông qua facade chỉ biết được các hành action như là: startNewDay, digOutGold, endDay, nhưng ko biết được
- startDay thì có những ai phải làm gì...
- Khi đào vàng thì phải chuẩn bị hay làm những gì...
- Khi kết thúc ngày làm việc thì phải chuẩn bị làm gì...
Java implementation
Đầu tiên là tạo subsystems DwarvenMineWorker
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* DwarvenMineWorker is one of the goldmine subsystems.
*
*/
public abstract class DwarvenMineWorker {
private static final Logger LOGGER = LoggerFactory.getLogger(DwarvenMineWorker.class);
public void goToSleep() {
LOGGER.info("{} goes to sleep.", name());
}
public void wakeUp() {
LOGGER.info("{} wakes up.", name());
}
public void goHome() {
LOGGER.info("{} goes home.", name());
}
public void goToMine() {
LOGGER.info("{} goes to the mine.", name());
}
private void action(Action action) {
switch (action) {
case GO_TO_SLEEP:
goToSleep();
break;
case WAKE_UP:
wakeUp();
break;
case GO_HOME:
goHome();
break;
case GO_TO_MINE:
goToMine();
break;
case WORK:
work();
break;
default:
LOGGER.info("Undefined action");
break;
}
}
/**
* Perform actions
*/
public void action(Action... actions) {
for (Action action : actions) {
action(action);
}
}
public abstract void work();
public abstract String name();
static enum Action {
GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_MINE, WORK
}
}
Tạo subsystem điều cho những worker thực hiện đào đường hầm DwarvenTunnelDigger
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* DwarvenTunnelDigger is one of the goldmine subsystems.
*
*/
public class DwarvenTunnelDigger extends DwarvenMineWorker {
private static final Logger LOGGER = LoggerFactory.getLogger(DwarvenTunnelDigger.class);
@Override
public void work() {
LOGGER.info("{} creates another promising tunnel.", name());
}
@Override
public String name() {
return "Dwarven tunnel digger";
}
}
Tạo subsystem điều cho những worker thực hiện vận chuyển DwarvenCartOperator
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* DwarvenCartOperator is one of the goldmine subsystems.
*
*/
public class DwarvenCartOperator extends DwarvenMineWorker {
private static final Logger LOGGER = LoggerFactory.getLogger(DwarvenCartOperator.class);
@Override
public void work() {
LOGGER.info("{} moves gold chunks out of the mine.", name());
}
@Override
public String name() {
return "Dwarf cart operator";
}
}
Tạo subsystem để điều khiển những chú lùn thực hiện đào DwarvenGoldDigger
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* DwarvenGoldDigger is one of the goldmine subsystems.
*
*/
public class DwarvenGoldDigger extends DwarvenMineWorker {
private static final Logger LOGGER = LoggerFactory.getLogger(DwarvenGoldDigger.class);
@Override
public void work() {
LOGGER.info("{} digs for gold.", name());
}
@Override
public String name() {
return "Dwarf gold digger";
}
}
Tạo facade DwarvenGoldmineFacade
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
*
* DwarvenGoldmineFacade provides a single interface through which users can operate the subsystems.
*
* This makes the goldmine easier to operate and cuts the dependencies from the goldmine user to the
* subsystems.
*
*/
public class DwarvenGoldmineFacade {
private final List<DwarvenMineWorker> workers;
/**
* Constructor
*/
public DwarvenGoldmineFacade() {
workers = new ArrayList<>();
workers.add(new DwarvenGoldDigger());
workers.add(new DwarvenCartOperator());
workers.add(new DwarvenTunnelDigger());
}
public void startNewDay() {
makeActions(workers, DwarvenMineWorker.Action.WAKE_UP, DwarvenMineWorker.Action.GO_TO_MINE);
}
public void digOutGold() {
makeActions(workers, DwarvenMineWorker.Action.WORK);
}
public void endDay() {
makeActions(workers, DwarvenMineWorker.Action.GO_HOME, DwarvenMineWorker.Action.GO_TO_SLEEP);
}
private static void makeActions(Collection<DwarvenMineWorker> workers,
DwarvenMineWorker.Action... actions) {
for (DwarvenMineWorker worker : workers) {
worker.action(actions);
}
}
}
Tạo client thực hiện điều khiển đào vàng
public class App {
/**
* Program entry point
*
* @param args command line args
*/
public static void main(String[] args) {
DwarvenGoldmineFacade facade = new DwarvenGoldmineFacade();
facade.startNewDay();
facade.digOutGold();
facade.endDay();
}
}
Run it.
Việc sử dụng facade về mặt phía client chỉ có 1 đầu mối duy nhất, toàn bộ các subsystem sẽ là trong suốt với clients.
Reference
Souce code tham khảo: https://github.com/ngodinhngoc/java-design-pattern/tree/master/facade
All Rights Reserved