public interface Observer { void update(Message message); }
public class ConcreteSubject implements Subject { private List<Observer> observers = new ArrayList<Observer>();
@Override public void registerObserver(Observer observer) { observers.add(observer); }
@Override public void removeObserver(Observer observer) { observers.remove(observer); }
@Override public void notifyObservers(Message message) { for (Observer observer : observers) { observer.update(message); } }
}
public class ConcreteObserverOne implements Observer { @Override public void update(Message message) { //TODO: 获取消息通知,执行自己的逻辑... System.out.println("ConcreteObserverOne is notified."); } }
public class ConcreteObserverTwo implements Observer { @Override public void update(Message message) { //TODO: 获取消息通知,执行自己的逻辑... System.out.println("ConcreteObserverTwo is notified."); } }
public class Demo { public static void main(String[] args) { ConcreteSubject subject = new ConcreteSubject(); subject.registerObserver(new ConcreteObserverOne()); subject.registerObserver(new ConcreteObserverTwo()); subject.notifyObservers(new Message()); } }
public interface RegObserver { void handleRegSuccess(long userId); }
public class RegPromotionObserver implements RegObserver { private PromotionService promotionService; // 依赖注入
@Override public void handleRegSuccess(long userId) { promotionService.issueNewUserExperienceCash(userId); } }
public class RegNotificationObserver implements RegObserver { private NotificationService notificationService;
@Override public void handleRegSuccess(long userId) { notificationService.sendInboxMessage(userId, "Welcome..."); } }
public class UserController { private UserService userService; // 依赖注入 private List<RegObserver> regObservers = new ArrayList<>();
// 一次性设置好,之后也不可能动态的修改 public void setRegObservers(List<RegObserver> observers) { regObservers.addAll(observers); }
public Long register(String telephone, String password) { //省略输入参数的校验代码 //省略userService.register()异常的try-catch代码 long userId = userService.register(telephone, password);
for (RegObserver observer : regObservers) { observer.handleRegSuccess(userId); }
public class UserController { private UserService userService; // 依赖注入
private EventBus eventBus; private static final int DEFAULT_EVENTBUS_THREAD_POOL_SIZE = 20;
public UserController() { //eventBus = new EventBus(); // 同步阻塞模式 eventBus = new AsyncEventBus(Executors.newFixedThreadPool(DEFAULT_EVENTBUS_THREAD_POOL_SIZE)); // 异步非阻塞模式 }
public void setRegObservers(List<Object> observers) { for (Object observer : observers) { eventBus.register(observer); } }
public Long register(String telephone, String password) { //省略输入参数的校验代码 //省略userService.register()异常的try-catch代码 long userId = userService.register(telephone, password);
eventBus.post(userId);
return userId; } }
public class RegPromotionObserver { private PromotionService promotionService; // 依赖注入
@Subscribe public void handleRegSuccess(Long userId) { promotionService.issueNewUserExperienceCash(userId); } }
public class RegNotificationObserver { private NotificationService notificationService;
@Subscribe public void handleRegSuccess(Long userId) { notificationService.sendInboxMessage(userId, "..."); } }
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.
public abstract class InputStream implements Closeable { //...省略其他代码... public int read(byte b[], int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; }
int c = read(); if (c == -1) { return -1; } b[off] = (byte)c;
int i = 1; try { for (; i < len ; i++) { c = read(); if (c == -1) { break; } b[off + i] = (byte)c; } } catch (IOException ee) { } return i; } public abstract int read() throws IOException; }
public class ByteArrayInputStream extends InputStream { //...省略其他代码... @Override public synchronized int read() { return (pos < count) ? (buf[pos++] & 0xff) : -1; } }
public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); boolean modified = false; for (E e : c) { add(index++, e); modified = true; } return modified; }
public void add(int index, E element) { throw new UnsupportedOperationException(); }
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; if (!(req instanceof HttpServletRequest && res instanceof HttpServletResponse)) { throw new ServletException("non-HTTP request or response"); } request = (HttpServletRequest) req; response = (HttpServletResponse) res; service(request, response); }
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1) { // servlet doesn't support if-modified-since, no reason // to go through further expensive logic doGet(req, resp); } else { long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); if (ifModifiedSince < lastModified) { // If the servlet mod time is later, call doGet() // Round down to the nearest second for a proper compare // A ifModifiedSince of -1 will always be less maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else { String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[1]; errArgs[0] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } }
下面看下 基于 Servlet 来开发一个Web项目的 hello world:
如果我们抛开这些高级框架来开发 Web 项目,必然会用到 Servlet。实际上,使用比较底层的 Servlet 来开发 Web 项目也不难。我们只需要定义一个继承 HttpServlet 的类,并且重写其中的 doGet() 或 doPost() 方法,来分别处理 get 和 post 请求。具体的代码示例如下所示:
public abstract class TestCase extends Assert implements Test { public void runBare() throws Throwable { Throwable exception = null; setUp(); try { runTest(); } catch (Throwable running) { exception = running; } finally { try { tearDown(); } catch (Throwable tearingDown) { if (exception == null) exception = tearingDown; } } if (exception != null) throw exception; } /** * Sets up the fixture, for example, open a network connection. * This method is called before a test is executed. */ protected void setUp() throws Exception { }
/** * Tears down the fixture, for example, close a network connection. * This method is called after a test is executed. */ protected void tearDown() throws Exception { } }
模板模式与Callback回调函数有何区别和联系?
什么是回调函数
相对于普通的函数调用,回调是一种双向调用关系。A 类事先注册某个函数 F 到 B 类,A 类在调用 B 类的 P 函数的时候,B 类反过来调用 A 类注册给它的 F 函数。这里的 F 函数就是“回调函数”。A 调用 B,B 反过来又调用 A,这种调用机制就叫作“回调”。
public interface ICallback { void methodToCallback(); }
public class BClass { public void process(ICallback callback) { //... callback.methodToCallback(); //... } }
public class AClass { public static void main(String[] args) { BClass b = new BClass(); b.process(new ICallback() { //回调对象 @Override public void methodToCallback() { System.out.println("Call back me."); } }); } }
@Override public <T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException { return query(sql, new RowMapperResultSetExtractor<T>(rowMapper)); }
@Override public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException { Assert.notNull(sql, "SQL must not be null"); Assert.notNull(rse, "ResultSetExtractor must not be null"); if (logger.isDebugEnabled()) { logger.debug("Executing SQL query [" + sql + "]"); }
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
public class StrategyFactory { private static final Map<String, Strategy> strategies = new HashMap<>();
static { strategies.put("A", new ConcreteStrategyA()); strategies.put("B", new ConcreteStrategyB()); }
public static Strategy getStrategy(String type) { if (type == null || type.isEmpty()) { throw new IllegalArgumentException("type should not be empty."); } return strategies.get(type);
public class StrategyFactory { public static Strategy getStrategy(String type) { if (type == null || type.isEmpty()) { throw new IllegalArgumentException("type should not be empty."); }
if (type.equals("A")) { return new ConcreteStrategyA(); } else if (type.equals("B")) { return new ConcreteStrategyB(); }
// 策略的创建 public class DiscountStrategyFactory { private static final Map<OrderType, DiscountStrategy> strategies = new HashMap<>();
static { strategies.put(OrderType.NORMAL, new NormalDiscountStrategy()); strategies.put(OrderType.GROUPON, new GrouponDiscountStrategy()); strategies.put(OrderType.PROMOTION, new PromotionDiscountStrategy()); }
public static DiscountStrategy getDiscountStrategy(OrderType type) { return strategies.get(type); } }
// 策略的使用 public class OrderService { public double discount(Order order) { OrderType type = order.getType(); DiscountStrategy discountStrategy = DiscountStrategyFactory.getDiscountStrategy(type); return discountStrategy.calDiscount(order); } }
重构之后的代码就没有了 if-else 分支判断语句了。实际上,这得益于策略工厂类。在工厂类中,我们用 Map 来缓存策略,根据 type 直接从 Map 中获取对应的策略,从而避免 if-else 分支判断逻辑。总结下本质,就是是借助“查表法”,根据 type查表来替代根据 type 分支判断。
public interface ISortAlg { void sort(String filePath); }
public class QuickSort implements ISortAlg { @Override public void sort(String filePath) { //... } }
public class ExternalSort implements ISortAlg { @Override public void sort(String filePath) { //... } }
public class ConcurrentExternalSort implements ISortAlg { @Override public void sort(String filePath) { //... } }
public class MapReduceSort implements ISortAlg { @Override public void sort(String filePath) { //... } }
public class SortAlgFactory { private static final Map<String, ISortAlg> algs = new HashMap<>();
static { algs.put("QuickSort", new QuickSort()); algs.put("ExternalSort", new ExternalSort()); algs.put("ConcurrentExternalSort", new ConcurrentExternalSort()); algs.put("MapReduceSort", new MapReduceSort()); }
public static ISortAlg getSortAlg(String type) { if (type == null || type.isEmpty()) { throw new IllegalArgumentException("type should not be empty."); } return algs.get(type); } }
public class Sorter { private static final long GB = 1000 * 1000 * 1000;
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
在职责链模式中,多个处理器(也就是刚刚定义中说的“接收对象”)依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。
Spring Interceptor,翻译成中文就是拦截器。与 Servlet Filter 一样,都可以实现对 HTTP 请求进行拦截处理。
Servlet Filter 是 Servlet 规范的一部分,实现依赖于 Web 容器。Spring Interceptor 是 Spring MVC 框架的一部分,由 Spring MVC 框架来提供实现。客户端发送的请求,会先经过 Servlet Filter,然后再经过 Spring Interceptor,最后到达具体的业务代码中。我画了一张图来阐述一个请求的处理流程,具体如下所示。
public class HandlerExecutionChain { private final Object handler; private HandlerInterceptor[] interceptors; public void addInterceptor(HandlerInterceptor interceptor) { initInterceptorList().add(interceptor); }
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for (int i = 0; i < interceptors.length; i++) { HandlerInterceptor interceptor = interceptors[i]; if (!interceptor.preHandle(request, response, this.handler)) { triggerAfterCompletion(request, response, null); return false; } } } return true; }
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception { HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for (int i = interceptors.length - 1; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; interceptor.postHandle(request, response, this.handler, mv); } } }
public MarioStateMachine() { this.score = 0; this.currentState = State.SMALL; }
public void obtainMushRoom() { executeEvent(Event.GOT_MUSHROOM); }
public void obtainCape() { executeEvent(Event.GOT_CAPE); }
public void obtainFireFlower() { executeEvent(Event.GOT_FIRE); }
public void meetMonster() { executeEvent(Event.MET_MONSTER); }
private void executeEvent(Event event) { int stateValue = currentState.getValue(); int eventValue = event.getValue(); this.currentState = transitionTable[stateValue][eventValue]; this.score += actionTable[stateValue][eventValue]; }
public int getScore() { return this.score; }
public State getCurrentState() { return this.currentState; }
}
状态机实现方式三:状态模式
在查表法的代码实现中,事件触发的动作只是简单的积分加减,所以,我们用一个 int 类型的二维数组 actionTable 就能表示,二维数组中的值表示积分的加减值。但是,如果要执行的动作并非这么简单,而是一系列复杂的逻辑操作(比如加减积分、写数据库,还有可能发送消息通知等等),我们就没法用如此简单的二维数组来表示了。这也就是说,查表法的实现方式有一定局限性。
@Override public boolean hasNext() { return cursor < arrayList.size(); }
@Override public void next() { cursor++; }
@Override public E currentItem() { if (cursor >= arrayList.size()) { throw new NoSuchElementException(); } return arrayList.get(cursor); } }
public interface List<E> { Iterator iterator(); }
public class ArrayList<E> implements List<E> { //... public Iterator iterator() { return new ArrayIterator(this); } //... }
public class Demo { public static void main(String[] args) { List<String> names = new ArrayList<>(); names.add("a"); names.add("b"); names.add("c"); names.add("d");
The command pattern encapsulates a request as an object, thereby letting us parameterize other objects with different requests, queue or log requests, and support undoable operations.
Mediator pattern defines a separate (mediator) object that encapsulates the interaction between a set of objects and the objects delegate their interaction to a mediator object instead of interacting with each other directly.