其他分享
首页 > 其他分享> > Observer观察者模式与OCP开放-封闭原则

Observer观察者模式与OCP开放-封闭原则

作者:互联网


目录


在学习Observer观察者模式时发现它符合敏捷开发中的OCP开放-封闭原则, 本文通过一个场景从差的设计开始, 逐步向Observer模式迈进, 最后的代码能体现出OCP原则带来的好处, 最后分享Observer模式在自己的项目中的实现.

场景引入

public class Observer {
    public static void main(String[] args) {
        Child c = new Child();
        Dad d = new Dad(c);
        new Thread(d).start();
        new Thread(c).start();
    }
}

class Child implements Runnable {
    boolean wakenUp = false;//是否醒了的标志, 供父亲线程探测

    public void wakeUp(){
        wakenUp = true;//醒后设置标志为true
    }

    @Override
    public void run() {
        try {
            Thread.sleep(3000);//睡3秒后醒来.
            wakeUp();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public boolean isWakenUp() {
        return wakenUp;
    }
}

class Dad implements Runnable{
    private Child c;

    public Dad(Child c){
        this.c = c;
    }

    public void feed(){
        System.out.println("feed child");
    }

    @Override
    public void run() {
        while(true){
            if(c.isWakenUp()){//每隔一秒看看孩子是否醒了
                feed();//醒了就喂饭
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

 

public class Observer {
    public static void main(String[] args) {
        Dad d = new Dad();
        Child c = new Child(d);
        new Thread(c).start();
    }
}

class Child implements Runnable {
    private Dad d;//持有父亲对象引用

    public Child(Dad d){
        this.d = d;
    }

    public void wakeUp(){
        d.feed();//醒来通知父亲喂饭
    }

    @Override
    public void run() {
        try {
            Thread.sleep(3000);//假设睡3秒后醒
            wakeUp();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class Dad{
    public void feed(){
        System.out.println("feed child");
    }
}

 

public class Observer {
    public static void main(String[] args) {
        Dad d = new Dad();
        Child c = new Child(d);
        new Thread(c).start();
    }
}

class Child implements Runnable {
    private Dad d;

    public Child(Dad d){
        this.d = d;
    }

    public void wakeUp(){//通过醒来事件让父亲作出响应
        d.actionToWakeUpEvent(new WakeUpEvent(System.currentTimeMillis(), this));
    }

    @Override
    public void run() {
        try {
            Thread.sleep(3000);
            wakeUp();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class Dad{
    public void actionToWakeUpEvent(WakeUpEvent event){
        System.out.println("feed child");
    }
}

class WakeUpEvent{
    private long time;//醒来的事件
    private Child source;//发出醒来事件的源

    public WakeUpEvent(long time, Child source){
        this.time = time;
        this.source = source;
    }
}
public class Observer {
    public static void main(String[] args) {
        Child c = new Child();
        c.addWakeUpListener(new Dad());
        c.addWakeUpListener(new GrandFather());
        c.addWakeUpListener(new Dog());
        new Thread(c).start();
    }
}

class Child implements Runnable {
    private ArrayListlist = new ArrayList<>();

    public void addWakeUpListener(WakeUpListener l){//对外提供注册监听的方法
        list.add(l);
    }

    public void wakeUp(){
        for(WakeUpListener l : list){//通知所有监听者
            l.actionToWakeUpEvent(new WakeUpEvent(System.currentTimeMillis(), this));
        }
    }

    @Override
    public void run() {
        try {
            Thread.sleep(3000);
            wakeUp();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

interface WakeUpListener{
    public void actionToWakeUpEvent(WakeUpEvent event);
}

class Dad implements WakeUpListener{
    @Override
    public void actionToWakeUpEvent(WakeUpEvent event){
        System.out.println("feed child");
    }
}

class GrandFather implements WakeUpListener{
    @Override
    public void actionToWakeUpEvent(WakeUpEvent event) {
        System.out.println("hug child");
    }
}

class Dog implements WakeUpListener{
    @Override
    public void actionToWakeUpEvent(WakeUpEvent event) {
        System.out.println("wang wang...");
    }
}

class WakeUpEvent{
    private long time;
    private Child source;//事件源

    public WakeUpEvent(long time, Child source){
        this.time = time;
        this.source = source;
    }
}

 

在联网坦克项目中使用观察者模式

    public boolean hitTank(Tank t) {//子弹击中坦克的方法
        if(this.live && t.isLive() && this.good != t.isGood() && this.getRect().intersects(t.getRect())) {
            this.live = false;//子弹死亡
            t.setLive(false);//坦克死亡
            tc.getExplodes().add(new Explode(x - 20, y - 20, tc));//产生一个爆炸
            return true;
        }
        return false;
    }
/**
 * 坦克被击中事件监听者(由坦克实现)
 */
public interface TankHitListener {
    public void actionToTankHitEvent(TankHitEvent tankHitEvent);
}

public class TankHitEvent {
    private Missile source;

    public TankHitEvent(Missile source){
        this.source = source;
    }
    //省略 get() / set() 方法...
}

/* 坦克类 */
public class Tank implements TankHitListener {
    //...
    
    @Override
    public void actionToTankHitEvent(TankHitEvent tankHitEvent) {
        this.tc.getExplodes().add(new Explode(tankHitEvent.getSource().getX() - 20,
                tankHitEvent.getSource().getY() - 20, this.tc));//坦克自身产生一个爆炸
        if(this.blood == 20){//坦克每次扣20滴血, 如果只剩下20滴了, 那么就标记为死亡.
            this.live = false;
            TankDeadMsg msg = new TankDeadMsg(this.id);//向其他客户端转发坦克死亡的消息
            this.tc.getNc().send(msg);
            this.tc.getNc().sendClientDisconnectMsg();//和服务器断开连接
            this.tc.gameOver();
            return;
        }
        this.blood -= 20;//血量减少20并通知其他客户端本坦克血量减少20.
        TankReduceBloodMsg msg = new TankReduceBloodMsg(this.id, tankHitEvent.getSource());//创建消息
        this.tc.getNc().send(msg);//向服务器发送消息
    }
    
    //...
}
/* 子弹类 */
public class Missile {
    //...
    
    public boolean hitTank(Tank t) {//子弹击中坦克的方法
        if(this.live && t.isLive() && this.good != t.isGood() && this.getRect().intersects(t.getRect())) {
            this.live = false;//子弹死亡
            t.actionToTankHitEvent(new TankHitEvent(this));//告知观察的坦克被打中了
            return true;
        }
        return false;
    }

    //...
}

 

总结

 

标签:小孩,Observer,void,Child,观察者,class,new,OCP,public
来源: https://blog.51cto.com/u_14797091/2758956