设计模式-java实现 简单易理解Demo[待续]

来源:互联网 发布:用java编写菱形图案 编辑:程序博客网 时间:2024/06/18 09:08

观察者模式


类图:
观察者模式

  • Subject被观察的目标
  • Observer 观察者

    Subject(Subject的子类)对象的发生改变的时候,通知所有的观察者,观察者做出响应。

代码(此处使用JAVA提供的Observable类/Observer接口):

被观察者

public class Account extends Observable {    private float mMoney = 0.0f;    public void add(float money ){        mMoney += money;        this.setChanged();        this.notifyObservers(mMoney);    }}

观察者

public class User implements Observer {    @Override    public void update(Observable o, Object arg) {        System.out.println("存款变了,通知User,存款为"+arg);    }}

Main

public class Main {    public static void main(String[] args) {        Observer user = new User();        Observer user2 = new User2();        Account account = new Account();        account.addObserver(user);        account.addObserver(user2);        account.add(99.f);    }}

在此处贴上ObservablesetChanged()notifyObservers()方法

    protected synchronized void setChanged() {        changed = true;    }    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);    }

代码很清晰了,在notifyObservers()方法中,对所有注册的观察者进行通知更新。

代理模式


类图:
这里写图片描述

  • Subject 共用接口,其中为被代理的方法。
  • RealSubject 被代理对象
  • Proxy代理对象

    代理即通过另一个类完成一个类改完成的方法,并在其基础上可以对其作出改变。在上图中,是通过聚合的方式。通过聚合或继承的方法实现代理,有兴趣可以看看java的代理实现,主要有两个类,ProxyInvocationHandler

代码(此处采用的实现方式是JDK代理)

接口

public interface Movable {    void move();}

被代理类

public class Car implements Movable {    @Override    public void move() {        System.out.println("汽车运行中");    }}

代理类

public class TimeProxy implements InvocationHandler {    private Movable movable;    public TimeProxy(Movable mov){        movable = mov;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("汽车开始运行");        long start = System.currentTimeMillis();        Object obj = method.invoke(movable, args);        long end = System.currentTimeMillis();        System.out.println("骑车结束运行,运行时间为:"+(end-start)+"毫秒");        return obj;    }}

Main

public class Main {    public static void main(String[] args) {        Car car = new Car();        TimeProxy timeProxy = new TimeProxy(car);        Movable movable = (Movable) Proxy.newProxyInstance(Car.class.getClassLoader(), Car.class.getInterfaces(), timeProxy);        movable.move();    }}

单例模式


单例模式,即在程序运行期间,单例类最多只可以有一个实例存在。单例模式的实现方法很多,各有优缺点,在此采用枚举实现单例(Effective Java Edition 2 第二章/第三条)。

单例类

public enum  BoyFriend  {    INSTANCE;    public void whatsName() {        System.out.println("code:" + this.hashCode());    }}

Main

public class Main {    public static void main(String[] args) {        BoyFriend boyFriend = BoyFriend.INSTANCE;        boyFriend.whatsName();        boyFriend.whatsName();    }}

实现非常简单,但是优点众多:线程安全、无法反射攻击、自动提供序列化支持等。。

责任链模式


这里写图片描述

  • Handler接口,规定传递请求的方法。
  • ConcreteHandleA 实现类,请求的具体执行者。
  • Client客户端,发出请求

    责任链模式,即通过一个链式的结构去处理请求,在每个节点,可以选择是通过还不是通过,通过即前往下一个节点,不通过,即退出责任链。

    下面模拟一个场景,女孩发出约会,看男孩有没有钱、房、车,有的话,继续看,没有就byebye,看代码。

Boy

public class Boy {    private boolean hasMoney;    private boolean hasCar;    private boolean hasHouse;    private Boy(){}    public Boy(boolean hasMoney, boolean hasCar, boolean hasHouse) {        this.hasMoney = hasMoney;        this.hasCar = hasCar;        this.hasHouse = hasHouse;    }    public boolean isHasMoney() {        return hasMoney;    }    public void setHasMoney(boolean hasMoney) {        this.hasMoney = hasMoney;    }    public boolean isHasCar() {        return hasCar;    }    public void setHasCar(boolean hasCar) {        this.hasCar = hasCar;    }    public boolean isHasHouse() {        return hasHouse;    }    public void setHasHouse(boolean hasHouse) {        this.hasHouse = hasHouse;    }}

接口

public interface Response {    void deliverResponse(Boy boy);}

实现类-得有车

public class CarResponse implements Response{    private Response next;    public CarResponse(Response res){        next = res;    }    @Override    public void deliverResponse(Boy boy) {        if(boy.isHasCar()){            System.out.println("有车呀,么么哒");            if(next != null){                next.deliverResponse(boy);            }        }else{            System.out.println("没车你说个jb");        }    }}

实现类-得有房

public class HouseResponse implements Response{    private Response next;    public HouseResponse(Response res){        next = res;    }    @Override    public void deliverResponse(Boy boy) {        if(boy`这里写代码片`.isHasHouse()){            System.out.println("有房呀,么么哒");            if(next != null){                next.deliverResponse(boy);            }        }else{            System.out.println("没房你说个jb.");        }    }}

实现类-得有钱

public class MoneyResponse implements Response{    private Response next;    public MoneyResponse(Response res){        next = res;    }    @Override    public void deliverResponse(Boy boy) {        if(boy.isHasMoney()){            System.out.println("有钱呀,么么哒");            if(next != null){                next.deliverResponse(boy);            }        }else{            System.out.println("没钱你说个jb");        }    }}

请求发出者 - Girl

public class Gril {    public void date(Boy boy){        Response r = new CarResponse(new HouseResponse(new MoneyResponse(null)));        r.deliverResponse(boy);    }}

Main

public class Main {    public static void main(String[] args) {        Gril gril = new Gril();        Boy boy = new Boy(false,true,false);        gril.date(boy);    }}

很清晰了,date()方法相当于发出一个请求,在各个Response中进行传递。

享元模式(附带工厂模式、单例模式)


享元模式,即通过建立一个缓存机制,将对象进行重用,而不需要每次调用进行重新创建,在本例中,使用HashTable实现对象缓存。

本例中,创建了两个实现Util接口的实现类,通过单例的UtilBox工厂获取Util的实现类,并在其中实现享元。

Util接口

public interface Util {    void use();    void putoff();}

实现类-钳子

public class Forceps implements Util {    public Forceps(){        try {            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }    }    @Override    public void use() {        System.out.println("用了个钳子");    }    @Override    public void putoff() {        System.out.println("放下了钳子");    }}

实现类 - 扳手

public class Wrench implements Util {    public Wrench(){        try {            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }    }    @Override    public void use() {        System.out.println("用了个扳手");    }    @Override    public void putoff() {        System.out.println("放下了扳手");    }}

工厂类

public enum UtilBox {    INSTANCE;    UtilBox() {        utilBoxTable =  new Hashtable<>();    }    private Hashtable<String,Util> utilBoxTable;    public Util getUtil(String utilName){        Util util = utilBoxTable.get(utilName);        if(util != null){            return util;        }        if("wrench".equals(utilName)){            util = new Wrench();            utilBoxTable.put("wrench",util);        }else if("forceps".equals(utilName)){            util = new Forceps();            utilBoxTable.put("forceps",util);        }else{            throw new IllegalArgumentException("utilName is not exists");        }        return util;    }}

Main

public class Main {    public static void main(String[] args) {        //通过观察,发现加载时间明显改变了        UtilBox.INSTANCE.getUtil("wrench").use();        UtilBox.INSTANCE.getUtil("wrench").use();        UtilBox.INSTANCE.getUtil("forceps").use();        UtilBox.INSTANCE.getUtil("forceps").use();    }}

代码没有什么难度,明白其中的意思即可。

备忘录模式


这里写图片描述

  • Originator 需要保存状态的类
  • Memento 状态记录类
  • Caretaker 记录状态的容器

    备忘录模式,即在不破坏原类封装的条件下,加入存储类和操作类记录原有类的状态变化。

原有类

public class Account {    private float money;    public float getMoney() {        return money;    }    public void setMoney(float money) {        this.money = money;    }    public Record save(){        return new Record(money);    }    public void restore(Record record){        money = record.money;    }    @Override    public String toString() {        return "账户余额为:"+money;    }}

备忘类

public class Record  {    float money;    public Record(float money) {        this.money = money;    }}

纪录类(本处采用Stack实现)

public class Memory {    private Stack<Record> memo;    public Memory(){        memo = new Stack<>();    }    public Record get(){        return memo.pop();    }    public void push(Record r){        memo.push(r);    }}

Main

public class Main {    public static void main(String[] args) {        Memory memory = new Memory();        Account a = new Account();        a.setMoney(12.0f);        memory.push(a.save());        System.out.println(a.toString());        a.setMoney(25.0f);        memory.push(a.save());        System.out.println(a.toString());        memory.get();        a.restore(memory.get());        System.out.println(a.toString());    }}

代码依然没难度,看明白就好。

策略模式

这里写图片描述

图片有点看不清楚,意思就是,通过聚合的方式,向原有类中添加功能。

鸭子 - 抽象类

public abstract class Duck {    public void swim(){        System.out.println(this.getClass().getSimpleName()+"游啊游");    }    public abstract void display();}

飞行的策略

public interface FlyStratagy {    void fly();}

飞行的策略实现

public interface FlyStratagy {    void fly();}

鸭子的实现 - 包含了飞行策略

public class WildDuck extends Duck {    private FlyStratagy fly;    public WildDuck(){        fly = new FlyWithWin();    }    @Override    public void display() {        System.out.println("灰色的鸭子");    }    public void fly(){        fly.fly();    }}

Main

public class Main  {    public static void main(String[] args) {        WildDuck duck = new WildDuck();        duck.fly();        duck.swim();        duck.display();    }}

策略模式的好处就是,将功能的添加采用聚合的模式,那么不会像接口那样,需要强制性的实现,并且策略可复用,在其他需要这个策略的地方,直接引入即可。
策略模式的详细说明可以参考《Effective Java edition 2》第四章第十八条:接口优于抽象类。

状态模式

这里写图片描述

状态模式,即通过状态,决定当前的行为,在发生了一定行为之后,进入下一个状态。

主体 - 灯

public class Light {    private LightState lightState;    public Light(){        lightState = new OffState();    }    public void setLightState(LightState ls){        lightState = ls;    }    public void switcher(){        lightState.handleState(this);    }}

状态接口

public interface LightState {    void handleState(Light light);}

状态实现 - 开灯状态

public class OnState implements LightState {    @Override    public void handleState(Light light) {        System.out.println("灯开着了");        light.setLightState(new OffState());    }}

状态实现 - 关灯状态

public class OffState implements LightState {    @Override    public void handleState(Light light) {        System.out.println("灯关了");        light.setLightState(new OnState());    }}

Main

public class Main {    public static void main(String[] args) {        Light light = new Light();        light.switcher();        light.switcher();        light.switcher();        light.switcher();    }}

通过lightswitcher()方法,改变了状态,触发状态改变,改变了light的行为,一直循环。

2015年6月16日 更新至此.
ps:以上图片均来自百度,侵删。
ps2:水平有限,如有不足,请指出。
ps3:代码可以在:简单设计模式Java实现 - github找到

0 0
原创粉丝点击