Java 设计模式 行为型模式 + 案例

行为型模式:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式

策略模式(Strategy)

策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,也可以设计一个抽象类(可有可无,属于辅助类),提供辅助函数

//统一的接口
    public interface ICalculator {
         public int calculate(String exp);
    }  

    //抽象类,作为辅助类,可以提供一些你认为需要的方法
    public abstract class AbstractCalculator {
        public int[] split(String exp,String opt){
            String array[] = exp.split(opt);
            int arrayInt[] = new int[2];
            arrayInt[0] = Integer.parseInt(array[0]);
            arrayInt[1] = Integer.parseInt(array[1]);
            return arrayInt;
        }
    } 

    //接口的三个实现类:
    public class Plus extends AbstractCalculator implements ICalculator {
        public int calculate(String exp) {
            int arrayInt[] = split(exp,"[+]");
            return arrayInt[0]+arrayInt[1];
        }
    }   

    public class Minus extends AbstractCalculator implements ICalculator {
        public int calculate(String exp) {
            int arrayInt[] = split(exp,"-");
            return arrayInt[0]-arrayInt[1];
        }
    }

    public class Multiply extends AbstractCalculator implements ICalculator {
        public int calculate(String exp) {
            int arrayInt[] = split(exp,"[*]");
            return arrayInt[0]*arrayInt[1];
        }
    }  

    //测试类
    public class Test {  

        public static void main(String[] args) {
            String exp = "2+8";
            ICalculator cal = new Plus();
            int result = cal.calculate(exp);
            System.out.println(result);
        }
    }

策略模式的决定权在用户,系统本身提供不同算法的实现,新增或者删除算法,对各种算法做封装。因此,策略模式多用在算法决策系统中,外部用户只需要决定用哪个算法即可。

我们之前在学校TreeSet排序的时候,有一种叫做资客户化排序的方式,就是给TreeSet传一个比较器对象,这个其实就是使用了策略模式

模板方法模式(Template Method)

模板方法模式,就是指:一个抽象类中,有一个主方法,再定义1…n个方法,可以是抽象的,也可以是实际的方法,定义一个类,继承该抽象类,重写抽象方法,通过调用抽象类的方法,实现对子类的调用其实就是我们之前所说的: 子类重新/实现父类中的方法,那么调用该方法的时候则是调用到了子类中重写之后的方法

//父类
    public abstract class AbstractCalculator {  

        /*实现对本类其它方法的调用*/
        public final int calculate(String exp,String opt){
            int array[] = split(exp,opt);
            return calculate(array[0],array[1]);
        }  

        /*被子类重写的方法*/
        abstract public int calculate(int num1,int num2);  

        public int[] split(String exp,String opt){
            String array[] = exp.split(opt);
            int arrayInt[] = new int[2];
            arrayInt[0] = Integer.parseInt(array[0]);
            arrayInt[1] = Integer.parseInt(array[1]);
            return arrayInt;
        }
    }       

    //子类
    public class Plus extends AbstractCalculator {
        public int calculate(int num1,int num2) {
            return num1 + num2;
        }
    }  

    //测试类
    public class Test {  

        public static void main(String[] args) {
            String exp = "8+8";
            AbstractCalculator cal = new Plus();
            int result = cal.calculate(exp, "\\+");
            System.out.println(result);
        }
    }

观察者模式(Observer)

观察者模式很好理解,类似于邮件订阅和RSS订阅,当我们浏览一些博客时,经常会看到RSS图标,就这的意思是,当你订阅了该文章,如果后续有更新,会及时通知你。其实,简单来讲就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。

我们在GUI那一章学习的事件监听机制就是可以这种设置模式来构建的代码

//观察者接口
    public interface Observer {
         public void update();
    }  

    //观察者1
    public class Observer1 implements Observer {
        public void update() {
            System.out.println("observer1 has received!");
        }
    }  

    //观察者2
    public class Observer2 implements Observer {
        public void update() {
            System.out.println("observer2 has received!");
        }
    } 

    //被观察者接口
    public interface Subject {  

        /*增加观察者*/
        public void add(Observer observer);  

        /*删除观察者*/
        public void del(Observer observer);  

        /*通知所有的观察者*/
        public void notifyObservers();  

        /*自身的操作*/
        public void operation();
    }  

    //被观察者的一个抽象实现 提供基本的实现
    public abstract class AbstractSubject implements Subject {  

        private Vector<Observer> vector = new Vector<Observer>();
        public void add(Observer observer) {
            vector.add(observer);
        }  

        public void del(Observer observer) {
            vector.remove(observer);
        }  

        public void notifyObservers() {
            Iterator<Observer> it = vector.iterator();
            while(it.hasNext()){
        Observer next = it.next();
        next.update();
            }
        }
    }

    //我们自己的一个被观察者实现  里面可以有我们自己的各种属性和方法
    public class MySubject extends AbstractSubject {
        public void operation() {
            System.out.println("update self!");
            notifyObservers();
        }
    } 

    //测试类
    public class Test {  

        public static void main(String[] args) {
            Subject sub = new MySubject();
            sub.add(new Observer1());
            sub.add(new Observer2());
            sub.operation();
        }
    }

迭代器模式(Iterator)

顾名思义,迭代器模式就是顺序访问聚集中的对象,一般来说,集合中非常常见,如果对集合类比较熟悉的话,理解本模式会十分轻松。

public interface Collection {
        public Iterator iterator();  

        /*取得集合元素*/
        public Object get(int i);  

        /*取得集合大小*/
        public int size();
    }  

    public interface Iterator {
        //前移  上一个元素
        public Object previous();  

        //后移  下一个元素
        public Object next();
        public boolean hasNext();  

        //取得第一个元素
        public Object first();
    }  

    public class MyCollection implements Collection {
        //假设这个集合内部是由数组实现
        public String string[] = {"A","B","C","D","E"};  

        public Iterator iterator() {
            return new MyIterator(this);
        }
        public Object get(int i) {
            return string[i];
        }
        public int size() {
            return string.length;
        }
    }  

    //这个地方其实一般会设计为内部类
    public class MyIterator implements Iterator {  

        private Collection collection;
        private int pos = -1;  

        public MyIterator(Collection collection){
            this.collection = collection;
        }
        public Object previous() {
            if(pos > 0){
                pos--;
            }
            return collection.get(pos);
        }
        public Object next() {
            if(pos<collection.size()-1){
                pos++;
            }
            return collection.get(pos);
        }
        public boolean hasNext() {
            if(pos<collection.size()-1){
                return true;
            }else{
                return false;
            }
        }
        public Object first() {
            pos = 0;
            return collection.get(pos);
        }
    }

    //测试类
    public class Test {  

        public static void main(String[] args) {
            Collection collection = new MyCollection();
            Iterator it = collection.iterator();  

            while(it.hasNext()){
                System.out.println(it.next());
            }
        }
    }

责任链模式(Chain of Responsibility)

责任链模式,有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求。但是发出者并不清楚到底最终那个对象会处理该请求,所以,责任链模式可以实现,在隐瞒客户端的情况下,对系统进行动态的调整。

(web应该中学习到的Filter其实就是一个责任链设计模式)

public interface Handler {
        public void operator();
    } 

    public class MyHandler implements Handler {  

        private String name;
        private Handler handler;  

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

        public Handler getHandler() {
            return handler;
        }
        public void setHandler(Handler handler) {
            this.handler = handler;
        }  

        public void operator() {
            System.out.println("name = "+name);
            if(getHandler()!=null){
                getHandler().operator();
            }
        }
    }  

    /测试类
    public class Test {  

        public static void main(String[] args) {
            MyHandler h1 = new MyHandler("h1");
            MyHandler h2 = new MyHandler("h2");
            MyHandler h3 = new MyHandler("h3");  

            h1.setHandler(h2);
            h2.setHandler(h3);  

            h1.operator();
        }
    }

命令模式(Command)

命令模式很好理解,举个例子,司令员下令让士兵去干件事情,从整个事情的角度来考虑,司令员的作用是,发出口令,口令经过传递,传到了士兵耳朵里,士兵去执行。这个过程好在,三者(司令、命令、士兵)相互解耦,任何一方都不用去依赖其他人的具体实现,只需要做好自己的事儿就行,司令员要的是结果,不会去关注到底士兵是怎么实现的。

//命令执行的接口
        public interface Command {
        public void exe();
    }
    //具体实现的命令
    public class MyCommand implements Command {  

        private Receiver receiver;  

        public MyCommand(Receiver receiver) {
            this.receiver = receiver;
        }
        public void exe() {
            receiver.action();
        }
    }   

    //被调用者(士兵)
    public class Receiver {
        public void action(){
            System.out.println("command received!");
        }
    }
    //调用者(司令员)
    public class Invoker {  

        private Command command;  

        public Invoker(Command command) {
            this.command = command;
        }  

        public void action(){
            command.exe();
        }
    }
    //测试类
    public class Test {  

        public static void main(String[] args) {
            Receiver receiver = new Receiver();
            Command cmd = new MyCommand(receiver);
            Invoker invoker = new Invoker(cmd);
            invoker.action();
        }
    }

这个很好理解,命令模式的目的就是达到命令的发出者和执行者之间解耦,实现请求和执行分开。

对于大多数请求-响应模式的功能,比较适合使用命令模式。

备忘录模式(Memento)

也可以叫备份模式,主要目的是保存一个对象的某个状态,以便在适当的时候恢复对象:假设有原始类A,A中有各种属性,A可以决定需要备份的属性,备忘录类B是用来存储A的一些内部状态,类C呢,就是一个用来存储备忘录的,且只能存储,不能修改等操作。

//原始类,里面有需要保存的属性value
    public class Original {  

        private String value;  

        public String getValue() {
            return value;
        }  

        public void setValue(String value) {
            this.value = value;
        }  

        public Original(String value) {
            this.value = value;
        }  

        //创建备忘录对象用来存储属性值
        public Memento createMemento(){
            return new Memento(value);
        }  

        //还原属性值
        public void restoreMemento(Memento memento){
            this.value = memento.getValue();
        }
    }       

    //备忘录类,用来保存value值
    public class Memento {  

        private String value;  

        public Memento(String value) {
            this.value = value;
        }  

        public String getValue() {
            return value;
        }  

        public void setValue(String value) {
            this.value = value;
        }
    } 

    //存储备忘录的类,持有Memento类的实例
    public class Storage {  

        private Memento memento;  

        public Storage(Memento memento) {
            this.memento = memento;
        }  

        public Memento getMemento() {
            return memento;
        }  

        public void setMemento(Memento memento) {
            this.memento = memento;
        }
    }  

    //测试类
    public class Test {  

        public static void main(String[] args) {  

            // 创建原始类
            Original origi = new Original("egg");  

            // 创建备忘录
            Storage storage = new Storage(origi.createMemento());  

            // 修改原始类的状态
            System.out.println("初始化状态为:" + origi.getValue());
            origi.setValue("niu");
            System.out.println("修改后的状态为:" + origi.getValue());  

            // 回复原始类的状态
            origi.restoreMemento(storage.getMemento());
            System.out.println("恢复后的状态为:" + origi.getValue());
        }
    } 

状态模式(State)

核心思想就是:当对象的状态改变时,同时改变其行为,很好理解!就拿QQ来说,有几种状态,在线、隐身、忙碌等,每个状态对应不同的操作。再比如交通灯,有红黄绿三种状态,每种状态下操作也是不一样的

//状态类
    public class State {  

        private String value;  

        public String getValue() {
            return value;
        }  

        public void setValue(String value) {
            this.value = value;
        }  

        public void method1(){
            System.out.println("execute the first opt!");
        }  

        public void method2(){
            System.out.println("execute the second opt!");
        }
    }

    //Context类可以实现切换状态
    public class Context {  

        private State state;  

        public Context(State state) {
            this.state = state;
        }  

        public State getState() {
            return state;
        }  

        public void setState(State state) {
            this.state = state;
        }  

        public void method() {
            if (state.getValue().equals("state1")) {
                state.method1();
            } else if (state.getValue().equals("state2")) {
                state.method2();
            }
        }
    } 

    //测试类
    public class Test {  

        public static void main(String[] args) {  

            State state = new State();
            Context context = new Context(state);  

            //设置第一种状态
            state.setValue("state1");
            context.method();  

            //设置第二种状态
            state.setValue("state2");
            context.method();
        }
    }  

访问者模式(Visitor)

访问者模式把数据结构和作用于结构上的操作解耦合,使得对数据操作可相对自由地演化。访问者模式适用于数据结构相对稳定,算法又易变化的系统。

因为访问者模式使得算法操作增加变得容易。若系统数据结构对象易于变化,经常有新的数据对象增加进来,则不适合使用访问者模式。访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者。访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统数据结构。其缺点就是增加新的数据结构很困难。

简单来说,访问者模式就是一种分离对象数据结构与行为的方法,通过这种分离,可达到为一个被访问者动态添加新的操作而无需做其它的修改的效果。

//访问者接口
    public interface Visitor {
        public void visit(Subject sub);
    }
    //访问者的一个具体实现
    public class MyVisitor implements Visitor {
        public void visit(Subject sub) {
            System.out.println("visit the subject:"+sub.getSubject());
        }
    }  

    //被访问者接口
    public interface Subject {
        public void accept(Visitor visitor);
        public String getSubject();
    }
    //被访问者的一个具体实现
    public class MySubject implements Subject {
        public void accept(Visitor visitor) {
            visitor.visit(this);
        }
        public String getSubject() {
            return "love";
        }
    }
    //测试类
    public class Test {  

        public static void main(String[] args) {  

            Visitor visitor = new MyVisitor();
            Subject sub = new MySubject();
            sub.accept(visitor);
        }
    } 

该模式适用场景:如果我们想为一个现有的类增加新功能,不得不考虑几个事情:

1、新功能会不会与现有功能出现兼容性问题?

2、以后会不会再需要添加?

3、如果类不允许修改代码怎么办?

面对这些问题,最好的解决方法就是使用访问者模式,访问者模式适用于数据结构相对稳定的系统,把数据结构和算法解耦

中介者模式(Mediator)

这个模式也是用来降低类和类之间的耦合的,因为如果类和类之间有依赖关系的话,不利于功能的拓展和维护,因为只要修改一个对象,其它关联的对象都得进行修改。如果使用中介者模式,只需关心和Mediator类的关系,具体类类之间的关系及调度交给Mediator就行

//中间者接口
    public interface Mediator {
        public void createMediator();
        public void workAll();
    }
    //中介者的一个具体实现
    public class MyMediator implements Mediator {  

        private User user1;
        private User user2;  

        public User getUser1() {
            return user1;
        }  

        public User getUser2() {
            return user2;
        }
        public void createMediator() {
            user1 = new User1(this);
            user2 = new User2(this);
        }
        public void workAll() {
            user1.work();
            user2.work();
        }
    }
    //抽象类
    public abstract class User {  

        private Mediator mediator;  

        public Mediator getMediator(){
            return mediator;
        }  

        public User(Mediator mediator) {
            this.mediator = mediator;
        }
        public abstract void work();
    }
    //User1
    public class User1 extends User {
        public User1(Mediator mediator){
            super(mediator);
        }
        public void work() {
            System.out.println("user1 exe!");
        }
    }
    //User2
    public class User2 extends User {
        public User2(Mediator mediator){
            super(mediator);
        }
        public void work() {
            System.out.println("user2 exe!");
        }
    }
    //测试类
    public class Test {  

        public static void main(String[] args) {
            Mediator mediator = new MyMediator();
            mediator.createMediator();
            mediator.workAll();
        }
    }  

适用场景

在面向对象编程中,一个类必然会与其他的类发生依赖关系,完全独立的类是没有意义的。一个类同时依赖多个类的情况也相当普遍,既然存在这样的情况,说明,一对多的依赖关系有它的合理性,适当的使用中介者模式可以使原本凌乱的对象关系清晰,但是如果滥用,则可能会带来反的效果。一般来说,只有对于那种同事类之间是网状结构的关系,才会考虑使用中介者模式。可以将网状结构变为星状结构,使同事类之间的关系变的清晰一些。

解释器模式(Interpreter)

在以下情况下可以使用解释器模式:

  • 有一个简单的语法规则,比如一个sql语句,如果我们需要根据sql语句进行其他语言的转换,就可以使用解释器模式来对语句进行解释。
  • 一些重复发生的问题,比如加减乘除四则运算,但是公式每次都不同,有时是a+b-c*d,有时是a*b+c-d,等等等等个,公式千变万化,但是都是由加减乘除四个非终结符来连接的,这时我们就可以使用解释器模式。
//解释器接口(这里的是专门解析数学运算表达式)
    public interface Expression {
         public int interpret(Context context);
    }
    //加法
    public class Plus implements Expression {
        public int interpret(Context context) {
            return context.getNum1()+context.getNum2();
        }
    }
    //减法
    public class Minus implements Expression {
        public int interpret(Context context) {
            return context.getNum1()-context.getNum2();
        }
    }  

    //Context类是一个上下文环境类 持有运行中所需的数据
    public class Context {  

        private int num1;
        private int num2;  

        public Context(int num1, int num2) {
            this.num1 = num1;
            this.num2 = num2;
        }  

        public int getNum1() {
            return num1;
        }
        public void setNum1(int num1) {
            this.num1 = num1;
        }
        public int getNum2() {
            return num2;
        }
        public void setNum2(int num2) {
            this.num2 = num2;
        }
    }  

    //测试类
    public class Test {  

        public static void main(String[] args) {  

                 // 计算9+2-8的值
                int result = new Minus().interpret(new Context(
                        new Plus().interpret(new Context(9, 2)), 8));
        //相当于:new Minus().interpret(new Context(11, 8));
        System.out.println(result);
        }
    }  

时间: 2024-11-08 21:15:18

Java 设计模式 行为型模式 + 案例的相关文章

java设计模式--行为型模式--迭代模式

1 迭代器模式 2 概述 3 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 4 5 6 适用性 7 1.访问一个聚合对象的内容而无需暴露它的内部表示. 8 9 2.支持对聚合对象的多种遍历. 10 11 3.为遍历不同的聚合结构提供一个统一的接口(即,支持多态迭代). 12 13 14 参与者 15 1.Iterator 16 迭代器定义访问和遍历元素的接口. 17 18 2.ConcreteIterator 19 具体迭代器实现迭代器接口.

java设计模式--行为型模式--命令模式

1 命令模式 2 概述 3 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤消的操作. 4 5 6 适用性 7 1.抽象出待执行的动作以参数化某对象. 8 9 2.在不同的时刻指定.排列和执行请求. 10 11 3.支持取消操作. 12 13 4.支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍. 14 15 5.用构建在原语操作上的高层操作构造一个系统. 16 17 18 参与者 19 1.Command 20 声明执行操作的接口.

java设计模式5--原型模式(Prototype)

本文地址:http://www.cnblogs.com/archimedes/p/java-prototype-pattern.html,转载请注明源地址. 原型模式 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 概述 原型模式是从一个对象出发得到一个和自己有相同状态的新对象的成熟模式,该模式的关键是将一个对象定义为原型,并为其提供复制自己的方法. java.lang.Object类的clone方法 参见<java中的深浅克隆> 适用性 1.当一个系统应该独立于它的产品创建

java设计模式--创建型模式

2016-04-24 10:10:34 创建型模式:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 注意:工厂模式可以分为三类: 1)简单工厂模式(Simple Factory) 2)工厂方法模式(Factory Method) 3)抽象工厂模式(Abstract Factory)  这三种模式从上到下逐步抽象,并且更具一般性.GOF在<设计模式>一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory).将简单工厂模式

java设计模式--行为型模式--状态模式

什么是行为型模式,小编觉得就是对行为的一种描述啦,一种对某种行为模型的定义. 状态模式: 1 状态模式 2 概述 3 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 4 5 6 适用性 7 1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为. 8 9 2.一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态. 10 这个状态通常用一个或多个枚举常量表示. 11 通常,有多个操作包含这一相同的条件结构.

Java设计模式——创建型模式之单例模式

一.概述 作为第一个出场的设计模式,有必要先介绍一下设计模式(引用自百度百科): 设计模式(Design Pattern)是一套被反复使用.多数人知晓的.经过分类的.代码设计经验的总结. 使用设计模式的目的:为了代码可重用性.让代码更容易被他人理解.保证代码可靠性. 设计模式使代码编写真正工程化:设计模式是软件工程的基石脉络,如同大厦的结构一样. 设计模式概念的介绍,参见:http://blog.jobbole.com/101076/ 其中涉及的设计原则的概念,参见随笔:http://www.c

java设计模式--行为型模式--中介者模式

怎么理解中介者模式,我姑且用房产中介来理解吧.呵呵 中介者模式: 1 中介者模式 2 概述 3 用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 4 5 6 适用性 7 1.一组对象以定义良好但是复杂的方式进行通信.产生的相互依赖关系结构混乱且难以理解. 8 9 2.一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象. 10 11 3.想定制一个分布在多个类中的行为,而又不想生成太多的子类. 12 13

java设计模式--行为型模式--策略模式

策略模式: 1 策略模式 2 概述 3 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换.本模式使得算法可独立于使用它的客户而变化. 4 5 适用性 6 1.许多相关的类仅仅是行为有异.“策略”提供了一种用多个行为中的一个行为来配置一个类的方法. 7 8 2.需要使用一个算法的不同变体. 9 10 3.算法使用客户不应该知道的数据.可使用策略模式以避免暴露复杂的.与算法相关的数据结构. 11 12 4.一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现. 13

java设计模式--创建型模式--抽象工厂

什么是抽象工厂,再次学习. 1 抽象工厂 2 概述 3 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 4 5 适用性 6 1.一个系统要独立于它的产品的创建.组合和表示时. 7 8 2.一个系统要由多个产品系列中的一个来配置时. 9 10 3.当你要强调一系列相关的产品对象的设计以便进行联合使用时. 11 12 4.当你提供一个产品类库,而只想显示它们的接口而不是实现时. 13 参与者 14 1.AbstractFactory 15 声明一个创建抽象产品对象的操作接口.