观察者模式与装饰者模式相遇的那些事
来源:互联网 发布:c 编程软件 编辑:程序博客网 时间:2024/05/16 14:43
一、题目与分析
题目:某企业准备研制一款带双屏幕显示的智能读卡器,该读卡器可以读取磁盘里的任一文件,并按照设定的读取模式在屏幕上显示。该读卡器有两种读取模式:一种小写模式,另一种倒序模式。
假设设定:
1、屏幕一只能按照信息小写模式的方式显示;屏幕二只能按照信息倒序模式的方式显示。
已知磁盘的文件名:MyFile.txt内容:
I KNOW YOU ARE STUDYING DESIGN PATTERNS.
2、屏幕一和屏幕二采取PULL方式获得信息。
请用正确的设计模式将上述需求设计出来并实现运行。
题目解读:如何从题目中抽取分析出该使用什么设计模式才能更好的解决需求呢?首先从题目入手,抽取题目关键字,智能读卡器,小写模式,倒序模式,屏幕一,屏幕二。然后把关键字的关系理清楚,屏幕一只能用小写模式显示信息,屏幕二只能用倒序模式显示信息,而小写模式和倒序模式是读卡器的功能。设计模式都是套路的,但是如何把这些套路如何来解决生活中的实际问题,就是我们需要掌握这些设计模式的理论知识。
下面是我设计的类图
首先把观察者和主题抽象类编写,然后屏幕一、屏幕二是具体观察者,具体主题只有一个是智能读卡器类,小写模式,倒序模式是工具类。把需求分析之后就开始编写类图,最后开始编码。
二、具体实现
1、主题抽象类Subject
public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers();}
2、具体主题类CardReaderSubject
public class CardReaderSubject implements Subject{ private ArrayList<Observer> observers; private String path; private String value; public CardReaderSubject(){ observers=new ArrayList<Observer>(); } @Override public void registerObserver(Observer o) { observers.add(o); } @Override public void removeObserver(Observer o) { int i=observers.indexOf(o); if(i>=0){ observers.remove(o); } } @Override public void notifyObservers() { for(int i=0;i<observers.size();i++){ Observer observer=(Observer)observers.get(i); if(observer instanceof ScreenOneObserver){ int c=0; String str=""; try{ InputStream in=new LowerCaseInputStream(new BufferedInputStream(new FileInputStream(path))); while((c=in.read())>=0){ str+=(char)c; } in.close(); }catch(IOException e){ e.printStackTrace(); } value=str; } if(observer instanceof ScreenTwoObserver){ int c=0; String str=""; try{ InputStream in=new InvertedOrderInputStream(new BufferedInputStream(new FileInputStream(path))); //c=0时,是把数据push进stack中,c大于0时就是pop数据出栈 while((c=in.read())>=0){ if(c!=0){ str+=(char)c; } } in.close(); }catch(IOException e){ e.printStackTrace(); } value=str; } observer.update(this); } } public void measurementsChanged(){ notifyObservers(); } public void setMeasurements(String path){ this.path=path; measurementsChanged(); } //提供观察者拉数据方法 public String getValue(){ return value; }}
3、观察者类Observer
public interface Observer {public void update(Subject subject);}
4、屏幕一类ScreenOneObserver
public class ScreenOneObserver implements Observer{ private Subject cardReaderSubject; private String value; public ScreenOneObserver(Subject cardReaderSubject){ this.cardReaderSubject=cardReaderSubject; cardReaderSubject.registerObserver(this); } @Override public void update(Subject subject) { CardReaderSubject cr=(CardReaderSubject)subject; value=cr.getValue(); //拉数据 System.out.println(value); }}
5、 屏幕二类ScreenTwoObserver
public class ScreenTwoObserver implements Observer{ private Subject cardReaderSubject; private String value; public ScreenTwoObserver(Subject cardReaderSubject){ this.cardReaderSubject=cardReaderSubject; cardReaderSubject.registerObserver(this); } @Override public void update(Subject subject) { CardReaderSubject cr=(CardReaderSubject)subject; this.value=cr.getValue(); //拉数据 System.out.println(value); }}
6、 倒序模式类InvertedOrderInputStream
public class InvertedOrderInputStream extends FilterInputStream{ private List<Integer> stack=new ArrayList<Integer>(); private int result=0; public InvertedOrderInputStream(InputStream in) { super(in); } public int read() throws IOException{ int c; if((c=super.read())>=0){ stack.add(0,c); return result; } if(stack.size()>0){ result=stack.get(0); stack.remove(0); return result; }else{ return -1; } } public int read(byte[] b,int offset,int len)throws IOException{ int result=super.read(b, offset, len); for(int i=offset;i<offset+result;i++){ b[i]=(byte)Character.toUpperCase((char)b[i]); } return result; }}
7、小写模式类LowerCaseInputStream
public class LowerCaseInputStream extends FilterInputStream{
protected LowerCaseInputStream(InputStream in) { super(in);}public int read() throws IOException{ int c=super.read(); return (c==-1?c:Character.toLowerCase((char)c));}public int read(byte[] b,int offset,int len)throws IOException{ int result=super.read(b, offset, len); for(int i=offset;i<offset+result;i++){ b[i]=(byte)Character.toLowerCase((char)b[i]); } return result;}
}
8、测试类Main
public class Main { public static void main(String[] args){ //选择的读取文件的路径 String path="e:\\test.txt"; CardReaderSubject cr=new CardReaderSubject(); ScreenOneObserver so=new ScreenOneObserver(cr); ScreenTwoObserver st=new ScreenTwoObserver(cr); cr.setMeasurements(path); }}
9、效果图
三、具体分析思路
可能一开始你会有很多的疑问,为什么会采用观察者模式和装饰者模式。采用装饰者模式是为了把读卡器的小写模式和倒序模式都通过继承FilterInputStream类,就可以把从文件读取的信息封装起来。供CardReaderSubject类使用。采用观察者模式是为了把智能读卡器内判断遇到屏幕一或屏幕二时,把他们订阅到Main主题对象中,然后就能动态监听遇到不同屏幕采用相应的读卡器读取模式。
- 观察者模式与装饰者模式相遇的那些事
- 策略模式+观察者模式+装饰者模式
- 装饰者模式,代理模式与适配器模式的比较
- 装饰者模式,代理模式与适配器模式的比较
- 设计模式(七)装饰者和观察者模式
- Head First设计模式之观察者,装饰者模式
- 关于复合模式、策略模式,工厂模式、观察者模式、装饰模式的一个好例子
- 装饰者模式与外观者模式的区别
- 装饰者模式与外观者模式的区别
- 代理模式与装饰者模式的区别
- 桥接模式与装饰者模式的区别
- 桥接模式与装饰者模式的区别
- 代理模式与装饰者模式的区别
- Java中装饰者模式与代理模式的使用
- 代理模式与装饰模式的异同
- 代理模式与装饰模式的区别
- 装饰模式与代理模式的区别
- 装饰模式与代理模式的区别
- Java实现-中序遍历和后续遍历构建二叉树
- Ubuntu16.04下基于GeForce1060显卡配置tensorflow-gpu
- Https完全协议详解
- spring 中常用的两种事务配置方式以及事务的传播性、隔离级别
- lucas定理
- 观察者模式与装饰者模式相遇的那些事
- ASP.Net中控件的EnableViewState属性
- Java中JNI的应用解析
- 使用 Spring Data JPA 简化 JPA 开发
- 40 C语言的两套标准
- JSON和JSONP的区别
- 找真正的入口(OEP)--广义ESP定律
- Spring事务配置的五种方式
- android 集成第三方静态库的编译方法