《设计模式之美》(四:行为型模式)

  1. 观察者模式
关键词 
Subject-Observer
Publisher-Subscriber
Producer-Consumer
EventEmitter-EventListener
Dispatcher-Listener
同步阻塞(一般默认),异步非阻塞,进程内,跨进程
如果要实现异步非阻塞就让notifyObserver在线程里面执行
public class Message {
    private String msg;

    public Message(String msg) {
        this.msg = msg;
    }

    public String getMsg() {
        return msg;
    }

    
}


public interface Observer {
    void onResult(Message message);
}

public interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers(Message message);
}

public class ConcreteSubject implements Subject{
    private List observers = new ArrayList<>();

    public void registerObserver(Observer observer){
        observers.add(observer);
    }

    public void removeObserver(Observer observer){
        observers.remove(observer);
    }

    public void notifyObservers(Message message){
        for (Observer observer: observers) {
            observer.onResult(message);
        }
    }
}


public class ConcernObserver1 implements Observer {
    @Override
    public void onResult(Message message) {
        System.out.println("i am ConcernObserver1 "+message.getMsg());
    }
}

public class ConcernObserver2 implements Observer {
    @Override
    public void onResult(Message message) {
        System.out.println("i am ConcernObserver2 "+message.getMsg());
    }
}

  public static void main(String[] args){
        ConcreteSubject concreteSubject = new ConcreteSubject();
        concreteSubject.registerObserver(new ConcernObserver1());
        concreteSubject.registerObserver(new ConcernObserver2());
        concreteSubject.notifyObservers(new Message("haha")); 
    }

手动实现一个EventBus
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Bean
public @interface Subscriber {

}

public class ObserverAction {
    private Object target;
    private Method method;

    public ObserverAction(Object target, Method method) {
        this.target = target;
        this.method = method;
    }

    public void executed(Object event){
        try {
            method.invoke(target,event);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

public class ObserverRegistry {
    //CopyOnWriteArraySet 写的时候,有个备份 不影响读; 多线程加锁限制
    private ConcurrentMap, CopyOnWriteArraySet> registry = new ConcurrentHashMap<>();

    public void register(Object observer){
        Map, Collection> observerActions = findAllObserverAction(observer);
        for(Map.Entry,Collection> entry : observerActions.entrySet()){
            Class eventType = entry.getKey();
            Collection eventActions = entry.getValue();
            CopyOnWriteArraySet registerEventActions = registry.get(eventType);
            if (registerEventActions == null){
                registry.putIfAbsent(eventType,new CopyOnWriteArraySet<>());
                registerEventActions = registry.get(eventType);
            }
            registerEventActions.addAll(eventActions);
        }
    }


    public List getMatchedObserverActions(Object event){
        List matchedActionList = new ArrayList<>();
        Class postedEventType = event.getClass();
        for (Map.Entry, CopyOnWriteArraySet> entry : registry.entrySet()){
            Class eventType = entry.getKey();
            CopyOnWriteArraySet eventActions = entry.getValue();
            if (postedEventType.isAssignableFrom(eventType)){
                matchedActionList.addAll(eventActions);
            }
        }
        return matchedActionList;

    }

    private Map, Collection> findAllObserverAction(Object observer){
        Map,Collection> observerActions = new HashMap<>();
        Class clazz = observer.getClass();
        for (Method method : getAnnotatedMethods(clazz)){
            Class[] parameterTypes = method.getParameterTypes();
            Class eventType = parameterTypes[0];
            if (!observerActions.containsKey(eventType)){
                observerActions.put(eventType,new ArrayList<>());
            }
            observerActions.get(eventType).add(new ObserverAction(observer,method));
        }
        return observerActions;
    }

    private List getAnnotatedMethods(Class clazz){
        List annotatedMethod = new ArrayList<>();
        for (Method method : clazz.getDeclaredMethods()){
            if (method.isAnnotationPresent(Subscriber.class)){
                Class[] parameterTypes = method.getParameterTypes();
                Preconditions.checkArgument(parameterTypes.length == 1,"Method %s has @Subscribe annotation but has %s parameters." + "Subscriber methods must have exactly 1 parameter.",
                        method, parameterTypes.length);
                annotatedMethod.add(method);
            }
        }
        return annotatedMethod;
    }

}

public class EventBus {
    private ObserverRegistry observerRegistry = new ObserverRegistry();
    private Executor executor;

    public EventBus() {
        this(MoreExecutors.directExecutor());
    }

    public EventBus(Executor executor) {
        this.executor = executor;
    }

    public void register(Object object){
        observerRegistry.register(object);
    }

    public void post(Object event){
        List matchedObserverActions = observerRegistry.getMatchedObserverActions(event);
        for (ObserverAction observerAction: matchedObserverActions) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    observerAction.executed(event);
                }
            });
        }
    }
}
  1. 模板模式
    • 定义:定义了方法的骨架,将某些步骤延迟到子类实现
    • 作用:复用和扩展
    • 模板和Callback:模板是继承,Callback是组合
public abstract class BaseTemplate {

    final void doTask(){
        before();
        System.out.println("BaseTemplate Task");
        after();
    }

    protected abstract void before();

    protected abstract void after();
}


public class ConcernTemplate extends BaseTemplate {
    @Override
    protected void before() {
     System.out.println("i am ConcernTemplate before");
    }

    @Override
    protected void after() {
        System.out.println("i am ConcernTemplate after");
    }
}

public interface ILoginService {
    void login(String userName,String pwd);
}

public class UserService {
    private ILoginService loginService;

    public void addLoginService(ILoginService loginService){
        this.loginService = loginService;
    }

    public void login(String userName,String pwd){
        if (loginService != null){
            loginService.login(userName,pwd);
        }else {
            throw new ExceptionInInitializerError("should call addLoginService before");
        }
    }

}

public static void main(String[] args){
        BaseTemplate template = new ConcernTemplate();
        template.doTask();

        UserService userService = new UserService();
        userService.addLoginService(new ILoginService() {
            @Override
            public void login(String userName, String pwd) {
                if ("tml".equals(userName) & "123".equals(pwd)){
                    System.out.println("login Success");
                }else {
                    System.out.println("login fail");
                }
            }
        });
        userService.login("tml","123");
    }
  1. 策略模式
    • 策略模式通常和工厂方法一起使用,策略模式重点在于灵活选择,工厂方法在于创建实例
    • 实现:缓存本地, if else(一个是代码写死,一个是配置文件,读取,动态);通过关系表,避免if else
public interface Strategy {
    void algorithmInterface();
}


public class ConcernStrategyA implements Strategy {
    @Override
    public void algorithmInterface() {
        System.out.println("ConcernStrategyA");
    }
}

public class ConcernStrategyB implements Strategy {
    @Override
    public void algorithmInterface() {
        System.out.println("ConcernStrategyB");
    }
}

public class ConcernStrategyC implements Strategy {
    @Override
    public void algorithmInterface() {
        System.out.println("ConcernStrategyB");
    }
}

//缓存  查表法 避免if else
public class StrategyFactory {
    private static Map strategies = new HashMap<>();

    static {
        strategies.put("A",new ConcernStrategyA());
        strategies.put("B",new ConcernStrategyA());
        strategies.put("C",new ConcernStrategyA());
    }

    public static Strategy getStrategy(String type){
        if (type == null || type.isEmpty()){
            throw new IllegalArgumentException("type should not be empty");
        }else {
            return strategies.get(type);
        }
    }
}

// if else
public class StrategyFactory1 {
    public static Strategy getStrategy(String type){
        if (type == null || type.isEmpty()){
            throw new IllegalArgumentException("type should not be empty");
        }else {
            if ("A".equals(type)){
                return new ConcernStrategyA();
            }else if("B".equals(type)){
                return new ConcernStrategyB();
            }else if ("C".equals(type)){
                return new ConcernStrategyC();
            }else {
                return null;
            }
        }
    }
}

  public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        properties.load(new FileInputStream("./config.properties"));
        String strategyType = (String) properties.get("strategy");
        Strategy strategy = StrategyFactory.getStrategy(strategyType);
        strategy.algorithmInterface();

        Strategy strategy1 = StrategyFactory1.getStrategy("A");
        strategy1.algorithmInterface();
    }

//config.properties
strategy:A

  1. 责任链模式
    • 应用:常用来开发过滤器和拦截器
    • 实例:Servlet Filter、Spring Interceptor
Filter & Interceptor & AOP 相同点与不同点
Filter依赖Servlet,作用于RSET api
Interceptor 依赖Spring Framework基于反射,作用于REST api
AOP 动态代理,作用于Bean
public abstract class Handler {
    Handler successor;

    public Handler() {
    }

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    public  void handle(){
        boolean handle = doHandle();
        if (!handle && successor != null){
            successor.handle();
        }
    };
    public abstract boolean doHandle();
}

public class HandlerA extends Handler {
    @Override
    public boolean doHandle() {
        System.out.println("AAA");
        return false;

    }
}

public class HandlerB extends Handler {
    @Override
    public boolean doHandle() {
        System.out.println("BBB");
        return false;
    }
}

public class HandleChain {
    private Handler head  = null;
    private Handler tail = null;

    public void addHandle(Handler handler){
        handler.setSuccessor(null);
        if (head == null){
            head = handler;
            tail = handler;
            return;
        }
        tail.setSuccessor(handler);
        tail = handler;
    }

    public void handle(){
        if (head != null){
            head.handle();
        }
    }
}

 public static void main(String[] args){
        HandleChain chain = new HandleChain();
        chain.addHandle(new HandlerA());
        chain.addHandle(new HandlerB());
        chain.handle();
        //还有一种直接在HandleChain存储一个列表或者数组 循环调用
    }
  1. 状态模式
    • 分支逻辑:if else 适合状态比较少
    • 查表法:二维数组,状态转移比较简单
    • 状态模式:相互耦合,适合事件触发比较复杂
public enum State {//状态
    Small(0),Super(1),Cape(2),Fire(3);

    private int state;
    State(int state) {
        this.state = state;
    }

    public int getState() {
        return state;
    }
}

public interface StateMachine {
    void obtainMushRoom();
    void obtainCap();
    void obtainFireFlower();
    void meetMonster();

}

// 方式一if else
public class MarioStateMachine implements StateMachine{
    State state = State.Small;
    int score;
    public void obtainMushRoom(){
        state = State.Super;
        score +=100;
    }

    public void obtainCap(){
        if (state == State.Small){
            state = State.Cape;
            score +=200;
        }else if(state == State.Super){
            state = State.Cape;
            score +=200;
        }
    }

    public void obtainFireFlower(){//事件
        if (state == State.Small){
            state = State.Fire;
            score +=300;
        }else if(state == State.Super){
            state = State.Fire;
            score +=300;
        }
    }

    public void meetMonster(){
        if (state == State.Super){
            state = State.Small;
            score -=100;
        }else if(state == State.Cape){
            state = State.Small;
            score -=200;
        }else if (state == State.Fire){
            state = State.Small;
            score -=300;
        }
    }
} 

public enum  Event {
    GOT_MushRoom(0),GOT_Cap(1),GOT_FireFlower(2),MEET_Monster(3);
    private int event;
    Event(int event) {
        this.event = event;
    }

    public int getEvent() {
        return event;
    }
}

//方式二 查表法
public class MarioStateMachine1 implements StateMachine{
    private int score;
    private State currentState;
   private static final  State[][] transitionTable = {{State.Super,State.Cape,State.Fire,State.Small},
            {State.Super,State.Cape,State.Fire,State.Small},
            {State.Cape,State.Cape,State.Cape,State.Small},
            {State.Fire,State.Fire,State.Fire,State.Small}};

    private static final int[][] actionTable = {{+100,+200,+300,+0},
            {+0,+300,+200,-100},
            {+0,+0,+0,-200},
            {+0,+0,+0,-300}};

    @Override
    public void obtainMushRoom() {
        executeEvent(Event.GOT_MushRoom);
    }

    @Override
    public void obtainCap() {
        executeEvent(Event.GOT_Cap);
    }

    @Override
    public void obtainFireFlower() {
        executeEvent(Event.GOT_FireFlower);
    }

    @Override
    public void meetMonster() {
        executeEvent(Event.MEET_Monster);
    }

    public void executeEvent(Event event){
        int event1 = event.getEvent();
        int state = currentState.getState();
        this.currentState = transitionTable[event1][state];
        this.score = score + actionTable[event1][state];
    }

}

public interface IMario {
    State getName();
    void obtainMushRoom();
    void obtainCap();
    void obtainFireFlower();
    void meetMonster();
}

//CapMario 等代码相似,省略
public class SmallMario implements IMario {
    private MarioStateMachine2 marioStateMachine;

    public SmallMario(MarioStateMachine2 marioStateMachine) {
        this.marioStateMachine = marioStateMachine;
    }

    @Override
    public State getName() {
        return State.Small;
    }

    @Override
    public void obtainMushRoom() {
        marioStateMachine.setMario(new SmallMario(marioStateMachine));
        marioStateMachine.setScore(marioStateMachine.getScore() + 100);
    }

    @Override
    public void obtainCap() {

    }

    @Override
    public void obtainFireFlower() {

    }

    @Override
    public void meetMonster() {

    }
}


//方式三 状态模式
public class MarioStateMachine2 {
    //省略一些代码
    private int score;
    private IMario mario;

    public int getScore() {
        return score;
    }

    public IMario getMario() {
        return mario;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public void setMario(IMario mario) {
        this.mario = mario;
    }
}
  1. 迭代器模式
    • ArrayIterator ArrayList 两者组合
比较:for 、foreach(语法糖,底层是Iterator)、Iterator 
对于数组列表三者方式都可以,但是对于复杂的数据结构,比如图,树,就不太方便
迭代器,增删元素有时候会导致出现异常,比较常用的处理方式是增删操作报错
迭代器有remove方法,遍历结合的时候可以安全的删除
可以采用为集合生产快照的方式来避免增删出错
  1. 访问模式
    将对象与操作解耦具体的操作,抽象一个操作类,然后传入具体的操作类实现

允许一个或多个操作应用在一组对象上,实现操作和对象解耦

ps:重载在大部分面向对象语言是静态绑定的,也就是说,调用类的哪个重载函数,是在编 译期间,由参数的声明类型决定的,而非运行时,根据参数的实际类型决定的
由于代码难以理解,所以一般不建议使用
public Class abstract ResourceFile{
String filePath;
public ResourceFile(String filePath){
    this.filePath = filePath
  }
abstract void accept(Visitor visitor)
}

public Class PdfFile extends ResourceFile{
  public PdfFile(String filePath) {
    super(filePath);
  }
void accept(Visitor visitor){
  visitor.visit(this)
  }
}

public Class WordFile extends ResourceFile{
  public PdfFile(String filePath) {
    super(filePath);
  }
void accept(Visitor visitor){
  visitor.visit(this)
  }
}

public Interface Visitor{
 void visit(PdfFile pdfFile);
  void visit(WordFile wordFile);
}

//读取文件
public class Extractor implements Visitor{
 void visit(PdfFile pdfFile){
  //......
  }
  void visit(WordFile wordFile){
  //......
  }
} 

//压缩文件
public class Compressor mplements Visitor{
 void visit(PdfFile pdfFile){
  //......
  }
  void visit(WordFile wordFile){
  //......
  }
} 


public static void main(String[] args){
  Extractor extractor = new Extractor();
  Compressor compressor =new Compressor();
  List files = loadFiles();
  for(ResourceFile file : files){
    file.accept(extractor)
    file.accept(compressor)
  }
}
  1. 备忘录模式
  2. 命令模式
  3. 解释器模式
  4. 中介模式

你可能感兴趣的:(《设计模式之美》(四:行为型模式))