美文网首页Java设计模式
《设计模式之美》(四:行为型模式)

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

作者: 文艺的程序狗 | 来源:发表于2020-08-11 16:32 被阅读0次
    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<Observer> 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<Class<?>, CopyOnWriteArraySet<ObserverAction>> registry = new ConcurrentHashMap<>();
    
        public void register(Object observer){
            Map<Class<?>, Collection<ObserverAction>> observerActions = findAllObserverAction(observer);
            for(Map.Entry<Class<?>,Collection<ObserverAction>> entry : observerActions.entrySet()){
                Class<?> eventType = entry.getKey();
                Collection<ObserverAction> eventActions = entry.getValue();
                CopyOnWriteArraySet<ObserverAction> registerEventActions = registry.get(eventType);
                if (registerEventActions == null){
                    registry.putIfAbsent(eventType,new CopyOnWriteArraySet<>());
                    registerEventActions = registry.get(eventType);
                }
                registerEventActions.addAll(eventActions);
            }
        }
    
    
        public List<ObserverAction> getMatchedObserverActions(Object event){
            List<ObserverAction> matchedActionList = new ArrayList<>();
            Class<?> postedEventType = event.getClass();
            for (Map.Entry<Class<?>, CopyOnWriteArraySet<ObserverAction>> entry : registry.entrySet()){
                Class<?> eventType = entry.getKey();
                CopyOnWriteArraySet<ObserverAction> eventActions = entry.getValue();
                if (postedEventType.isAssignableFrom(eventType)){
                    matchedActionList.addAll(eventActions);
                }
            }
            return matchedActionList;
    
        }
    
        private Map<Class<?>, Collection<ObserverAction>> findAllObserverAction(Object observer){
            Map<Class<?>,Collection<ObserverAction>> 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<Method> getAnnotatedMethods(Class<?> clazz){
            List<Method> 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<ObserverAction> 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<String,Strategy> 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. 访问模式
    2. 备忘录模式
    3. 命令模式
    4. 解释器模式
    5. 中介模式

    相关文章

      网友评论

        本文标题:《设计模式之美》(四:行为型模式)

        本文链接:https://www.haomeiwen.com/subject/xhbedktx.html