美文网首页
《设计模式之禅》学习及源码示例---观察者模式\模板方法模式\策

《设计模式之禅》学习及源码示例---观察者模式\模板方法模式\策

作者: 笔记本一号 | 来源:发表于2021-01-01 03:22 被阅读0次

一、观察者模式

定义:

定义对象一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新

组成角色:
Subject被观察者:

通常为抽象类,能够动态添加,取消观察者,管理观察者并通知观察者

Observer观察者:

通常是个接口,观察者收到消息就进行update(更新方法)操作,对收到的信息进行处理

ConcreteSubject具体的被观察者:

定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知

ConcreteObserver具体的观察者:

定义每个观察者自己处理通知的逻辑

需求:各个狗仔队爆料蔡徐坤各种信息,蔡徐坤一有什么动静就马上爆料他
//Subject被观察者
public abstract class Subject {
    private List<Observer> observers=new ArrayList<>();
//定义Observer观察者的添加删除,管理Observer观察者
    public void addObserver(Observer observer){
        observers.add(observer);
    }

    public void delObserver(Observer observer){
        observers.remove(observer);
    }
//通知Observer观察者
    public void notifyObservers(String action){
        observers.forEach(o->o.update(action));
    }
//Subject被观察者的行为
    abstract void playBasketball();

    abstract void rap();

    abstract void dance();
}
//Observer观察者接口
public interface Observer {
    void update(String action);
}
//具体的被观察者实现
public class ConcreteSubjectCxk extends Subject {
    private final static String NAME="蔡徐坤";
    @Override
    void playBasketball() {
        String action=NAME+"打篮球";
        System.out.println(NAME+"打篮球");
        super.notifyObservers(action);
    }

    @Override
    void rap() {
        String action=NAME+"唱rap";
        System.out.println(action);
        super.notifyObservers(action);
    }

    @Override
    void dance() {
        String action=NAME+"跳舞";
        System.out.println(NAME+"跳舞");
        super.notifyObservers(action);
    }
}
//具体的观察者实现
public class ConcreteObserverDog1 implements Observer{
    private String name;

    public ConcreteObserverDog1(String name) {
        this.name = name;
    }

    @Override
    public void update(String action) {
        System.out.println(name+"爆料"+action);
    }
}
public class ConcreteObserverDog2 implements Observer{
    private String name;

    public ConcreteObserverDog2(String name) {
        this.name = name;
    }

    @Override
    public void update(String action) {
        System.out.println(name+"爆料"+action);
    }
}
public class ConcreteObserverDog3 implements Observer{
    private String name;

    public ConcreteObserverDog3(String name) {
        this.name = name;
    }

    @Override
    public void update(String action) {
        System.out.println(name+"爆料"+action);
    }
}

测试

public class Test {
    public static void main(String[] args) {
        Observer observer1=new ConcreteObserverDog1("狗子队1号");
        Observer observer2=new ConcreteObserverDog2("狗子队2号");
        Observer observer3=new ConcreteObserverDog3("狗子队3号");
        Subject cxk=new ConcreteSubjectCxk();
        cxk.addObserver(observer1);
        cxk.addObserver(observer2);
        cxk.addObserver(observer3);
        cxk.playBasketball();
    }

源码使用示例:

在jdk中自带了观察者模式的类包
这是jdk给我们提供的被观察者的类,我们可以通过继承实现观察者模式,利用这个类代替上面的Subject

package java.util;
public class Observable {
    private boolean changed = false;
    private Vector<Observer> obs;
    public Observable() {
        obs = new Vector<>();
    }
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }
synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }
    public void notifyObservers() {
        notifyObservers(null);
    }
    public void notifyObservers(Object arg) {
        Object[] arrLocal;
        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }
        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }
    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }
    protected synchronized void setChanged() {
        changed = true;
    }
    protected synchronized void clearChanged() {
        changed = false;
    }
    public synchronized boolean hasChanged() {
        return changed;
    }
    public synchronized int countObservers() {
        return obs.size();
    }
}

这是jdk给我们提供的观察者

package java.util;
public interface Observer {
    void update(Observable o, Object arg);
}

现在我们利用jdk给我们提供的完成上面爆料蔡徐坤的功能

//定义要爆料的行为接口
public interface Icxk {
     void playBasketball();
     void rap();
     void dance();
}
import java.util.Observable;
//继承JDK给我们提供的被观察者类Observable 
public class ConcreteSubjectCxk extends Observable implements Icxk{
    private final static String NAME="蔡徐坤";

    @Override
    public void playBasketball() {
//调用Observable 类的setChanged()方法才会启动观察者模式
        super.setChanged();
        String action=NAME+"打篮球";
        System.out.println(NAME+"打篮球");
        super.notifyObservers(action);
    }

    @Override
    public void rap() {
        super.setChanged();
        String action=NAME+"唱rap";
        System.out.println(action);
        super.notifyObservers(action);
    }

    @Override
    public void dance() {
        super.setChanged();
        String action=NAME+"跳舞";
        System.out.println(NAME+"跳舞");
        super.notifyObservers(action);
    }
}

import java.util.Observable;
import java.util.Observer;
//狗仔队的类实现jdk给我们提供的观察者接口Observer 
public class ConcreteObserverDog1 implements Observer {
    private String name;
    public ConcreteObserverDog1(String name) {
        this.name = name;
    }
    @Override
    public void update(Observable o, Object arg) {
        System.out.println(name+"爆料"+arg.toString());
    }
}

后面省略几个狗子队的具体实现类....
测试

public class Test {
    public static void main(String[] args) {
        java.util.Observer observer1=new ConcreteObserverDog1("狗子队1号");
        java.util.Observer observer2=new ConcreteObserverDog2("狗子队2号");
        java.util.Observer observer3=new ConcreteObserverDog3("狗子队3号");
        ConcreteSubjectCxk cxk=new ConcreteSubjectCxk();
        //jdk的观察者模式是从集合的末尾执行
        cxk.addObserver(observer3);
        cxk.addObserver(observer2);
        cxk.addObserver(observer1);
        cxk.playBasketball();
        
    }
}

二、模板方法模式

定义:

定义一次操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤

组成角色:
AbstractClass:模板类

提供模板算法的抽象类

ConcreteClass:模板类的实现子类

模板类的实现子类

需求:卖苹果11,根据不同顾客的需求卖不同配置的苹果11
public abstract class AbstractIPhone11 {
    public void battery(){
        System.out.println("电池:3110mAh");
    }
    public void CPU(){
        System.out.println("CPU:A13");
    }
    public void RAM(){
        System.out.println("RAM:4GB");
    }
    public void bulid(String c){
        System.out.println("顾客"+c+"你的手机配置为:");
        battery();
        CPU();
        RAM();
        coustomer();
        System.out.println("");
    }
    //提供顾客填写需要的配置
    public abstract void coustomer();

}
public class Customer1 extends AbstractIPhone11{
    @Override
    public void coustomer() {
        System.out.println("color:黄色");
        System.out.println("ROM:64GB");
    }
}
public class Customer2 extends AbstractIPhone11{
    @Override
    public void coustomer() {
        System.out.println("color:黑色");
        System.out.println("ROM:128GB");
    }
}

测试

public class Test {
    public static void main(String[] args) {
        AbstractIPhone11 c1=new Customer1();
        c1.bulid("c1");
        AbstractIPhone11 c2=new Customer2();
        c2.bulid("c2");
    }
}

源码使用示例:

1、AbstractList是ArrayList的父类,在AbstractList中,其get方法和addAll方法都是提供可以提供子类去实现,其中get是个抽象方法完全需要子类去实现。

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
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;
    }
abstract public E get(int index);
....
}

2、servelt中相应处理请求的HttpServlet类,是一个抽象类,它采用的是模板方法,来实现根据不同的请求,调用不同的方法,其中HttpServlet类中的service采就是这个核心的方法。根据的请求头的类型来决定执行哪个方法,也就是上图中说的定义了算法的骨架的方法。如下,一堆doGet,doHead,doPost,doPut,doDelete...是需要我们继承HttpServlet去重写实现相应的逻辑,通常我们只要重写doGet和doPost

public abstract class HttpServlet extends GenericServlet {
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentException var9) {
                    ifModifiedSince = -1L;
                }

                if (ifModifiedSince < lastModified / 1000L * 1000L) {
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
            this.doPost(req, resp);
        } else if (method.equals("PUT")) {
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
            this.doTrace(req, resp);
        } else {
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }

    }
}

重写doGet和doPost实现不一样的Servlet不一样的处理逻辑

@WebServlet(name = "/test")
public class Test extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       ......
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       ......
    }
}

三、策略模式

定义:

定义一组算法,将每个算法都封装起来,并且使它们之间可以互换

组成角色:
Context封装角色:

通过封装隐蔽策略的具体细节,转化并执行策略的方法,根据不同的参数执行不同的策略

Strategy抽象策略角色:

策略的抽象方法或者接口

ConcreteStrategy策略的具体角色:

策略的具体方法实现

需求:批发水果,根据时段不同卖的价格不同,早上卖5块钱一斤,中午4块钱一斤,晚上2块钱一斤
public interface Strategy {
    void price();
}
public class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void price(){
        strategy.price();
    }
}
public class ConcreteStrategyMorning implements Strategy{
    @Override
    public void price() {
        System.out.println("葡萄5块钱一斤");
    }
}
public class ConcreteStrategyNoon implements Strategy{
    @Override
    public void price() {
        System.out.println("葡萄3块钱一斤");
    }
}
public class ConcreteStrategyNight implements Strategy{
    @Override
    public void price() {
        System.out.println("葡萄2块钱一斤");
    }
}
public class Test {
    public static void main(String[] args) {
        Context context;
        System.out.println("现在是早上");
        context=new Context(new ConcreteStrategyMorning());
        context.price();
        System.out.println("\n");

        System.out.println("现在是中午");
        context=new Context(new ConcreteStrategyNoon());
        context.price();
        System.out.println("\n");

        System.out.println("现在是晚上");
        context=new Context(new ConcreteStrategyNight());
        context.price();
        System.out.println("\n");
    }
}

源码使用示例:

在JDK线程池中ThreadPoolExecutor类就是使用的是策略模式,RejectedExecutionHandler 参数是拒绝策略的接口,通过传入不同的拒绝策略接口实现对象,执行不一样的策略

  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }
public interface RejectedExecutionHandler {
    void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

相关文章

网友评论

      本文标题:《设计模式之禅》学习及源码示例---观察者模式\模板方法模式\策

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