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

本文深入讲解了多种设计模式,包括观察者模式、代理模式、单例模式等,并提供了详细的Java实现示例。

观察者模式


类图:
观察者模式

  • 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找到

创建型模式 这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。 工厂模式(Factory Pattern) 抽象工厂模式(Abstract Factory Pattern) 单例模式(Singleton Pattern) 建造者模式(Builder Pattern) 原型模式(Prototype Pattern) 2 结构型模式 这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。 适配器模式(Adapter Pattern) 桥接模式(Bridge Pattern) 过滤器模式(Filter、Criteria Pattern) 组合模式(Composite Pattern) 装饰器模式(Decorator Pattern) 外观模式(Facade Pattern) 享元模式(Flyweight Pattern) 代理模式(Proxy Pattern) 3 行为型模式 这些设计模式特别关注对象之间的通信。 责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解释器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式(Mediator Pattern) 备忘录模式(Memento Pattern) 观察者模式(Observer Pattern) 状态模式(State Pattern) 空对象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 访问者模式(Visitor Pattern) 4 J2EE 模式 这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。 MVC 模式(MVC Pattern) 业务代表模式(Business Delegate Pattern) 组合实体模式(Composite Entity Pattern) 数据访问对象模式(Data Access Object Pattern) 前端控制器模式(Front Controller Pattern) 拦截过滤器模式(Intercepting Filter Pattern) 服务定位器模式(Service Locator Pattern) 传输对象模式(Transfer Object Pattern)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值