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

观察者模式


类图:
观察者模式

  • 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值