设计模式面试必备知识点掌握

设计模式面试总结

原文链接:链接

1.策略模式

定义了算法簇,进行封装,他们之间可以相互替换
实现:接口类来实现算法簇;可以用类的继承或者抽象类的继承来实现个体

2.观察者模式

手动实现:
两个接口 subject:registerObserver(),removeOberver(),notifyOberver()
Oberver:update()
采用 List来保存observer,通过迭代来调用每一个List里面的Observer的update方法
java实现
一个类:Oberverable:addOberver(),deleteObserver(),notifyObervers(),setChanged()
一个接口
Oberver:update()
采用Vector来保存observer,setChanged来通知变化。

Vector & ArrayList
1) Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。
2) 当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小,这样,ArrayList就有利于节约内存空间。
Hashtable & HashMap
Hashtable和HashMap它们的性能方面的比较类似 Vector和ArrayList,比如Hashtable的方法是同步的,而HashMap的不是。
ArrayList & LinkedList
ArrayList的内部实现是基于内部数组Object[],所以从概念上讲,它更象数组,但LinkedList的内部实现是基于一组连接的记录,所以,它更象一个链表结构,所以,它们在性能上有很大的差别:
从上面的分析可知,在ArrayList的前面或中间插入数据时,你必须将其后的所有数据相应的后移,这样必然要花费较多时间,所以,当你的操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能; 而访问链表中的某个元素时,就必须从链表的一端开始沿着连接方向一个一个元素地去查找,直到找到所需的元素为止,所以,当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。
http://wiki.jikexueyuan.com/project/java-collection/linkedhashmap.html

反应器模式与观察者模式的异同

反应器模式

是一种为处理服务请求并发提交到一个或者多个服务处理程序的事件设计模式。当请求抵达后,服务处理程序使用解多路分配策略,然后同步地派发这些请求至相关的请求处理程序。

观察者模式

有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

将事件多路分用、将事件分派到各自相应的事件处理程序。

分布式系统中的服务器应用程序必须处理多个向它们发送服务请求的客户机。然而,在调用特定的服务之前,服务器应用程序必须将每个传入请求多路分用并分派到各自相应的服务提供者。反应器模式正好适用于这一功能。它允许事件驱动应用程序将服务请求多路分用并进行分派,然后,这些服务请求被并发地从一个或多个客户机传送到应用程序。

反应器模式(Reactor pattern)与观察者模式(Observer pattern)在这个方面极为相似:
当一个主体发生改变时,所有依属体都得到通知。
不过
观察者模式与单个事件源关联,而反应器模式则与多个事件源关联。
反应器设计模式(Reactor pattern)是一种为处理服务请求并发 提交到一个或者多个服务处理程序的事件设计模式。当请求抵达后,服务处理程序使用解多路分配策略,然后同步地派发这些请求至相关的请求处理程序。

装饰者模式

一个抽象类作为初始类
一些实际的工具
装饰类集成自抽象类
实际的装饰类继承自装饰类
Java 的IO

工厂模式与抽象工厂模式还有简单工厂模式

简单工厂模式:一个类搞定
工厂模式:由子类去决定生产什么(抽象类)
既子类继承工厂,实现创造方法
抽象工厂:定义了一个接口,所有的实际工厂实现此接口。用于创建相关或对象的家族,而不需要制定具体类

单例模式

双重检查
饱汉与饿汉:饱汉getInstance方法创建对象
饿汉:定义为static方法或者放在static块中,在类加载时就初始化了

命令模式

封装命令(接口),由实际命令去实现命令接口,调用者调用命令。

用在队列请求(日程安排、线程池、工作队列)、日志请求

将请求封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象,命令模式也支持可撤销的操作。

适配器模式

将一个类的接口,转换成客户期望的另一个接口

旧的枚举迭代器。新的迭代器适配,将旧的适配成新的枚举

外观模式

提供一个统一的接口,用来访问子系统中的一群接口,提供一个高层接口让子系统更容易使用

模板方法模式
在一个方法中定义一个算法的顾家,而将一些步骤延迟到子类中上线。

模板方法在不改变算法结构的情况下,重新定义算法的某些步骤

迭代器模式

java.util.Iterator
提供一种方法顺序访问一个聚合对象中的各个元素

组合模式

将对象组合成树形结构来表现“整体/部分”的层次结构,中间的调用,可以用迭代器来建立

状态模式

允许对象在内部状态改变时改变他的行为,对象看起来好像修改了他的类。

代理模式

RMI
为另一个对象提供一个替身或者占位符,以控制对这个对象的访问

分为远程代理,和虚拟代理

虚拟代理:一个接口
分别由 被代理者 和 代理者实现

MVC模式

使用了
对象行为类的设计模式,对同步事件分拣和派发。

Dispatcher(分发器),Notifer(通知器)

应用程序提供的每种服务对应一个独立的Event Handler,每种Handler处理一种类型的事件。所有的Event Handler有接口。这样,不同的Event Handler会注册到Initiation Dispacher, Initiation Dispatcher使用Synchronous Event Demultiplexer等待事件的发生。事件发生时,Demultiplexer通知Dispacher,Dispatcher回调Handler,Handler调用对应的事件处理方法。

和观察者模式(Observer)[5]相关,当一个对象改变,其他多个模块被通知。在反应堆模式中,当某个Handle感有兴趣的事件发生,Handler被通知。反应堆模式用来分拣多个事件源的事件,而观察者模式常常只关联一个事件源。
和责任链模式相关(Chain of Responsibility)[5],当把一个请求委托给服务提供者。反应堆模式与责任链不同,反应堆模式关联一个特定的事件处理器到特定的事件源,而责任链模式搜索一个序列去定义第一个匹配的事件处理器。
反应堆模式还被认为是异步Proactor[18]模式的同步变种,Proactor支持异步事件源的事件分拣和多个事件处理器的分派。不同的时,反应堆模式支持的是没有阻塞的同步事件源。
主动对象模式[17]分离了方法的执行和调用,简化了多个线程调用时同步控制的复杂性(这个模式我也翻译过了),。当多线程不可用,或者任务使用多线程太复杂了,反应堆模式经常替换主动对象。
在实现反应堆模式的时候,可以提供一个外观(Facade)[5]类处理事件的分拣。一个外观类用来隐藏一个子系统中复杂的对象关系

常用设计模式(面试)

原文链接:链接

Singleton(单例模式)

一句话总结:一个类在Java虚拟机中只有一个对象,并提供一个全局访问点。
生活中例子:太阳、月亮、国家主席等。
解决什么问题:对象的唯一性,性能浪费太多。
项目里面怎么用:数据库连接对象,属性配置文件的读取对象。
模式结构:分为饿汉式和懒汉式(如果考虑性能问题的话,就使用懒汉式,因为懒汉式是在方法里面进行初始化的),构造器私 有化,对外提供方法加同步关键字。
框架里面使用:Struts1的Action。
JDK里面使用:java.lang.Runtime#getRuntimejava.awt.Desktop#getDesktop。
饿汉式代码:

  1. public class HurgrySingleton {
  2. private static HurgrySingleton hurgry=new HurgrySingleton();
  3. private HurgrySingleton(){};
  4. public static HurgrySingleton getSinletonHurgry(){
  5. return hurgry;
  6. }

懒汉式代码:

  1. public class LarzySingleton {
  2. private static LarzySingleton larzy=null;
  3. private LarzySingleton(){};
  4. public static synchronized Larzy getSinletonLarzy(){
  5. if(larzy==null){
  6. larzy=new LarzySingleton();
  7. }
  8. return larzy;
  9. }
  10. }

Factory(简单的工厂模式)

一句话总结:用一个方法来代替new关键字
生活中的例子:制衣厂、面包厂等生产厂。
解决什么问题:对象产生过多,或者经常有子类替换生成。
项目里面怎么用:对于经常生成的对象,或者父子类替换的对象。
模式结构:写一个对外声明的方法,方法里面使用new关键字代替。
框架里面使用:spring的核心就是工厂模式。
JDK里面使用:newInstance。
工厂模式代码:

  1. public class UserFactory {
  2. public static User createUser(int i){
  3. //如果输入的是1,就创建它的子类,否则就创建父类
  4. if(i==1){
  5. return new Alices();
  6. }
  7. return new User();
  8. }
  9. }

Proxy(代理模式)

一句话总结:为其他对象提供一个代理,以控制对当前对象的访问。
生活中的例子:房屋中介、婚姻介绍所。
解决什么问题:不能直接访问该对象,或者太大的资源耗费多。
项目里面怎么用:权限,或者大对象的访问权限。
模式结构:代理类和被代理类实现同一个接口,用户访问的时候先访问代理对象,然后让代理对象去访问被代理对象。
框架里面使用:Spring里面的AOP实现。
JDK里面使用:java.lang.reflect.Proxy。
代理模式代码:
创建一个接口:

  1. public interface SellHouse {
  2. void sell(double money);
  3. }

创建一个被代理类:

  1. public class Hoster implements SellHouse {
  2. @Override
  3. public void sell(double money) {
  4. System.out.println("祝你居住愉快");
  5. }
  6. }

创建一个代理类:

  1. public class Medium implements SellHouse {
  2. SellHouse hoster=new Hoster();
  3. @Override
  4. public void sell(double money) {
  5. if(money>=1000){
  6. hoster.sell(money);
  7. }else{
  8. System.out.println("你的价格太低了");
  9. }
  10. }
  11. }

测试类:

  1. public class Renter {
  2. public static void main(String[] args) {
  3. SellHouse renter=new Medium();
  4. renter.sell(500);
  5. }
  6. }

Adapter(适配器模式)

一句话总结:将两个原来不兼容的类兼容起来一起工作。
生活中的例子:变压器、充电器
解决什么问题:已经存在的相同功能的代码,但是接口不兼容,不能直接调用。
项目里面怎么用:在使用旧的API的时候,没有源码,和新的不能兼容。
模式结构:分为类适配器和对象适配,一般常用的就是对象适配器,因为组合由于继承。
框架里面使用:单元测试里面的asserEquels。
JDK里面使用:java.util.Arrays#asListjava.io.InputStreamReader(InputStream) java.io.outputStreamWriter(OutputStream)。

Strategy(策略模式)

一句话总结:定义一系列算法并可以互相替换。
生活中的例子:图片的格式,压缩文件的格式。
解决什么问题:做一件事情有很多种方法。
项目里面怎么用:购物车里面的付款方式。
模式结构:声明一个顶级接口,定义一个策略方法,具体的实例都要实现这个接口。
框架里面使用:hibernate的主键生成策略。
JDK里面使用:java.util.Comparator#compare。
策略模式代码:
定义一个顶级接口:

  1. public interface Person {
  2. void repast();
  3. }

具体的实例类1:

  1. public class African implements Person {
  2. @Override
  3. public void repast() {
  4. System.out.println("非洲人用手吃饭");
  5. }
  6. }

具体的实例类2:

  1. public class America implements Person {
  2. @Override
  3. public void repast() {
  4. System.out.println("美国人用刀叉吃饭");
  5. }
  6. }

具体的实例类3:

  1. public class Chinese implements Person {
  2. @Override
  3. public void repast() {
  4. System.out.println("中国人用筷子吃饭");
  5. }
  6. }

测试类:

  1. public class Test {
  2. public static void main(String[] args) {
  3. Person chinese=new Chinese();
  4. Person america=new America();
  5. Person african=new African();
  6. chinese.repast();
  7. america.repast();
  8. african.repast();
  9. }
  10. }

Template(模板模式)

一句话总结:父类定义流程,子类实现流程。
生活中的例子:iphone生产有多个国家,但流程只有一个。
解决什么问题:业务有多种,但都有规定的流程。
项目里面怎么用:一般基类的实现都是模板模式,BaseDAO,bBaseService。
模式结构:定义一个抽象父类定义流程,或者常用方法和常量,子类继承父类,实现具体的细节方法。
框架里面使用:hibernate里面的方言,是跨数据库的基础。
JDK里面使用:IO流里面的InputStream,Writer等。
模板模式代码:
//定义一个父类,定义流程

  1. public abstract class IPhoneTemplate {
  2. public void createIPhone(){
  3. setupCpu();
  4. setupAll();
  5. check();
  6. box();
  7. }
  8. protected abstract void box();
  9. protected abstract boolean check();
  10. protected abstract void setupAll();
  11. protected abstract void setupCpu();
  12. }

//子类实现父类的细节方法1

  1. public class ChinaIPhone extends IPhoneTemplate {
  2. @Override
  3. protected void box() {
  4. System.out.println("box()");
  5. }
  6. @Override
  7. protected boolean check() {
  8. System.out.println("check()");
  9. return true;
  10. }
  11. @Override
  12. protected void setupAll() {
  13. System.out.println("setupAll()");
  14. }
  15. @Override
  16. protected void setupCpu() {
  17. System.out.println("setupCpu()");
  18. }
  19. }

//子类实现父类的细节方法2

  1. public class AfricanIPhone extends IPhoneTemplate {
  2. @Override
  3. protected void box() {
  4. System.out.println("box()");
  5. }
  6. @Override
  7. protected boolean check() {
  8. System.out.println("check()");
  9. return true;
  10. }
  11. @Override
  12. protected void setupAll() {
  13. System.out.println("setupAll()");
  14. }
  15. @Override
  16. protected void setupCpu() {
  17. System.out.println("setupCpu()");
  18. }
  19. }

Java中常用的设计模式

原文链接:链接

1.单例模式

  单例模式有以下特点:
  1、单例类只能有一个实例。
  2、单例类必须自己创建自己的唯一实例。
  3、单例类必须给所有其他对象提供这一实例。
  单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
  总之,选择单例模式就是为了避免不一致状态,避免政出多头。
推荐链接:http://blog.csdn.net/jason0539/article/details/23297037

2.工厂模式

  工厂模式的两种情况:
  1.在编码时不能预见需要创建哪种类的实例。
  2.系统不应依赖于产品类实例如何被创建、组合和表达的细节
推荐链接:http://www.cnblogs.com/poissonnotes/archive/2010/12/01/1893871.html

3.建造着模式

  该模式其实就是说,一个对象的组成可能有很多其他的对象一起组成的,比如说,一个对象的实现非常复杂,有很多的属性,而这些属性又是其他对象的引用,可能这些对象的引用又包括很多的对象引用。封装这些复杂性,就可以使用建造模式。
推荐链接:http://www.cnblogs.com/cbf4life/archive/2010/01/14/1647710.html

4.门面模式

  这个模式个人感觉像是Service层的一个翻版。比如Dao我们定义了很多持久化方法,我们通过Service层将Dao的原子方法组成业务逻辑,再通过方法向上层提供服务。

  • 为一个复杂子系统提供一个简单接口

  • 提高子系统的独立性

  • 在层次化结构中,可以使用Facade模式定义系统中每一层的入口

推荐链接:http://www.cnblogs.com/skywang/articles/1375447.html

5.策略模式

  感觉没找到写的特别好的博客,可能是不合胃口。小编喜欢用实际例子来讲的博客。下面的链接是360百科的解释。
推荐链接:http://baike.so.com/doc/1838412-1944078.html

面试常考设计模式

原文链接:链接

(1)一个线程安全且高效率的单利模式

  1. //一个很好的单例模式
  2. public class DesignModel1 {
  3. private static DesignModel1 instance;
  4. //把构造器私有化
  5. private DesignModel1(){};
  6. public static DesignModel1 getInstance() {
  7. if(instance ==null) {
  8. synchronized (DesignModel1.class) {
  9. if(instance==null) {
  10. instance = new DesignModel1();
  11. }
  12. }
  13. }
  14. return instance;
  15. }
  16. }

(2)工厂模式:通过对象构造工厂在构建相应的对象实例

  1. interface Animal{
  2. public void say();
  3. }
  4. class Cat implements Animal{
  5. @Override
  6. public void say() {
  7. System.out.println("I am a cat");
  8. }
  9. }
  10. class Dog implements Animal{
  11. @Override
  12. public void say() {
  13. System.out.println("I am a dog");
  14. }
  15. }
  16. class Factory{
  17. public static Animal getInstance(String className) {
  18. //通过equal方法在确定类的实例
  19. Animal ani = null;
  20. if("cat".equals(className)) {
  21. ani = new Cat();
  22. }
  23. if("dog".equals(className)) {
  24. ani = new Dog();
  25. }
  26. return ani;
  27. }
  28. }
  29. public class DesignModel2 {
  30. public static void main(String[] args) {
  31. Animal a = null; // 定义接口对象
  32. a = Factory.getInstance(args[0]); // 通过工厂获取实例
  33. if (a != null) { // 判断对象是否为空
  34. a.say(); // 调用方法
  35. }
  36. }
  37. }

(3)代理模式:对代理类进行动态的扩展

  1. /**
  2. * 代理模式就是多一个代理类出来,替原对象进行一些操作
  3. * 例如买房子找中介,上法院找律师等等
  4. */
  5. interface Sourceable1 {
  6. public void method();
  7. }
  8. class Source1 implements Sourceable {
  9. @Override
  10. public void method() {
  11. System.out.println("the original method!");
  12. }
  13. }
  14. //注意装饰器模式持有的是接口的实例,代理模式持有的是实现类的实例
  15. class Proxy1 implements Sourceable1{
  16. private Source1 source1;
  17. public Proxy1() {
  18. super();
  19. this.source1 = new Source1();
  20. }
  21. //重写Sourceable1的method()方法,并且持有的Source1实现类是实例也进行操作
  22. @Override
  23. public void method() {
  24. before();
  25. source1.method();
  26. after();
  27. }
  28. private void before() {
  29. System.out.println("before proxy!");
  30. }
  31. private void after() {
  32. System.out.println("after proxy!");
  33. }
  34. }
  35. public class DesignModel7 {
  36. public static void main(String[] args) {
  37. Sourceable1 source = new Proxy1();
  38. source.method();
  39. }
  40. }

(4)适配器模式

  1. /**
  2. *适配器模式:一个接口可能有多个的实现方法,但是我们不需继承一个接口全部的实现它
  3. *而是用一个抽象类继承接口,然后我们选择性的继承即可
  4. *
  5. */
  6. interface Window {// 定义Window窗口接口,表示窗口操作
  7. public void open();// 窗口打开
  8. public void close();// 窗口关闭
  9. public void iconified();// 窗口最小化
  10. public void deiconified();// 窗口恢复
  11. public void activated();// 窗口活动
  12. }
  13. //定义抽象类实现接口,在此类中覆写方法,但是所有的方法体为空
  14. abstract class WindowAdapter implements Window {
  15. public void open() {
  16. };// 窗口打开
  17. public void close() {
  18. };// 窗口关闭
  19. public void iconified() {
  20. };// 窗口最小化
  21. public void deiconified() {
  22. };// 窗口恢复
  23. public void activated() {
  24. };// 窗口活动
  25. }
  26. //子类继承WindowAdapter抽象类,选择性实现需要的方法
  27. class WindowImpl extends WindowAdapter {
  28. public void open() {
  29. System.out.println("窗口打开");// 实现open()方法
  30. }
  31. public void close() {
  32. System.out.println("窗口关闭");// 实现close()方法
  33. }
  34. }
  35. public class DesignModel4 {
  36. public static void main(String args[]) {
  37. Window win = new WindowImpl(); // 实现接口对象
  38. // 调用方法
  39. win.open();
  40. win.close();
  41. }
  42. }

(5)构造者模式

  1. /**
  2. *
  3. *构造者模式
  4. */
  5. interface Sender {
  6. public void Send();
  7. }
  8. class MailSender implements Sender {
  9. @Override
  10. public void Send() {
  11. System.out.println("this is mailsender!");
  12. }
  13. }
  14. class SmsSender implements Sender {
  15. @Override
  16. public void Send() {
  17. System.out.println("this is sms sender!");
  18. }
  19. }
  20. //MailSender和SmsSender为Sender的接口实现类,所以可以在list中加入
  21. //DesignModel5一个类管理着多个对象的实例
  22. public class DesignModel5 {
  23. private List<Sender> list = new ArrayList<Sender>();
  24. public void produceMailSender(int count){
  25. for(int i=0; i<count; i++){
  26. list.add(new MailSender());
  27. }
  28. }
  29. public void produceSmsSender(int count){
  30. for(int i=0; i<count; i++){
  31. list.add(new SmsSender());
  32. }
  33. }
  34. public static void main(String[] args) {
  35. DesignModel5 builder = new DesignModel5();
  36. builder.produceMailSender(10);
  37. }
  38. }

(6)装饰模式

  1. //装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例
  2. interface Sourceable {
  3. public void method();
  4. }
  5. //本来Source方法继承了Sourceable实现了method()方法
  6. class Source implements Sourceable {
  7. @Override
  8. public void method() {
  9. System.out.println("the original method!");
  10. }
  11. }
  12. //Decorator持有Sourceable的属性,对其进行装饰
  13. class Decorator implements Sourceable {
  14. private Sourceable source;
  15. public Decorator(Sourceable source){
  16. super();
  17. this.source = source;
  18. }
  19. @Override
  20. public void method() {
  21. System.out.println("before decorator!");
  22. source.method();
  23. System.out.println("after decorator!");
  24. }
  25. }
  26. public class DesignModel6 {
  27. public static void main(String[] args) {
  28. //接口不能单独的实例化,必须通过实现类来帮助实例化
  29. Sourceable source = new Source();
  30. Sourceable obj = new Decorator(source);
  31. obj.method();
  32. }
  33. }

(7)观察者模式

  1. interface Observer{
  2. public void updata();
  3. }
  4. class Observer1 implements Observer{
  5. @Override
  6. public void updata() {
  7. System.out.println("observer1 has received!");
  8. }
  9. }
  10. class Observer2 implements Observer{
  11. @Override
  12. public void updata() {
  13. System.out.println("observer2 has received!");
  14. }
  15. }
  16. interface Subject{
  17. /*增加观察者*/
  18. public void add(Observer observer);
  19. /*删除观察者*/
  20. public void del(Observer observer);
  21. /*通知所有的观察者*/
  22. public void notifyObservers();
  23. /*自身的操作*/
  24. public void operation();
  25. }
  26. abstract class AbstractSubject implements Subject{
  27. private List<Observer> observers = new ArrayList<>();
  28. @Override
  29. public void add(Observer observer) {
  30. observers.add(observer);
  31. }
  32. @Override
  33. public void del(Observer observer) {
  34. observers.remove(observer);
  35. }
  36. @Override
  37. public void notifyObservers() {
  38. Iterator<Observer> ite = observers.iterator();
  39. while(ite.hasNext()) {
  40. ite.next().updata();
  41. }
  42. }
  43. }
  44. class MySubject extends AbstractSubject{
  45. @Override
  46. public void operation() {
  47. System.out.println("udpate self");
  48. notifyObservers();
  49. }
  50. }
  51. public class DesignModel8 {
  52. public static void main(String[] args) {
  53. Subject sub = new MySubject();
  54. sub.add(new Observer1());
  55. sub.add(new Observer2());
  56. sub.operation();
  57. }
  58. }

20个设计模式和软件设计面试问题

原文链接:链接
对中高级别的设计模式面试问题
这是一些和设计模式还有软件设计都相关的问题。这些问题需要一些思考和经验来回答。在大多数情况下,面试官并不是需要一个确切的答案,而是希望听到你的想法,你对这个问题是怎么考虑的,你能不能想通这个问题,能不能挖掘一些没有告诉你的潜在信息。在解决一个问题时你应该考虑什么等等可以使你经验大涨。总的来说,这些设计问题会让你动起脑来。有时面试官也会让你写代码,所以还是准备一下吧。如果你知道编程和设计技巧中的概念,例子和程序,你应该可以在这些问题中有突出的表现。

  1. 举出一个例子,在这种情况你会更倾向于使用抽象类,而不是接口?

这是很常用但又是很难回答的设计面试问题。接口和抽象类都遵循”面向接口而不是实现编码”设计原则,它可以增加代码的灵活性,可以适应不断变化的需求。下面有几个点可以帮助你回答这个问题:

在Java中,你只能继承一个类,但可以实现多个接口。所以一旦你继承了一个类,你就失去了继承其他类的机会了。
接口通常被用来表示附属描述或行为如:Runnable、Clonable、Serializable等等,因此当你使用抽象类来表示行为时,你的类就不能同时是Runnable和Clonable(译者注:这里的意思是指如果把Runnable等实现为抽象类的情况),因为在Java中你不能继承两个类,但当你使用接口时,你的类就可以同时拥有多个不同的行为。
在一些对时间要求比较高的应用中,倾向于使用抽象类,它会比接口稍快一点。
如果希望把一系列行为都规范在类继承层次内,并且可以更好地在同一个地方进行编码,那么抽象类是一个更好的选择。有时,接口和抽象类可以一起使用,接口中定义函数,而在抽象类中定义默认的实现。
希望了解更多关于Java接口的,可以看我的文章Java接口需要知道的10件事。

  1. 设计一个贩卖机,可以接收不同的货币,出售不同的产品?

这是一个开放设计问题,你可以作为练习,尝试着写出设计文档、代码和JUnit测试而不是只是解决这个问题,看看它花了你多少时间得到解决方案和得到需要的原形。理想情况下,这个问题应该可以在3个小时内解决,至少应该得到一个可以运行的版本。

  1. 你有一个Smartphone类,可以派生如IPhone、AndroidPhone、WindowsMobilePhone类

它还可以是一些有着品牌的手机名称,你会怎么设计这个类系统呢。

这是另外一个设计模式练习,你可以应用你的面向对象设计技巧来得到一个设计,这个设计需要足够灵活能够支持未来产品的扩展,足够稳定能够支持在现有模型进行修改。

  1. 在Java中,什么时候用重载,什么时候用重写?

对有经验的Java设计师来说,这是一个相当简单的问题。如果你看到一个类的不同实现有着不同的方式来做同一件事,那么就应该用重写(overriding),而重载(overloading)是用不同的输入做同一件事。在Java中,重载的方法签名不同,而重写并不是。

  1. 设计一个ATM机?

我们所有人都使用ATM(自动柜员机)。想想你会怎么设计一个ATM?就设计金融系统来说,必须知道它们应该在任何情况下都能够如期工作。不管是断电还是其他情况,ATM应该保持 正确的状态(事务) , 想想 加锁(locking)、事务(transaction)、错误条件(error condition)、边界条件(boundary condition) 等等。尽管你不能想到具体的设计,但如果你可以指出非功能性需求,提出一些问题,想到关于边界条件,这些都会是很好的一步。

  1. 你正在写一些类提供市场数据,你知道你可以不定时切换不同的厂商如Reuters、wombat或者直接的批发商, 你会如何设计你的市场数据系统。

这是一个非常有趣的设计面试问题,并且真的在一家大的投资银行问到过,如果你是用Java编码的话这是一个相当平常的场景。最主要的一点是你要有一个MarketData接口,它会有调用端需要的方法如:getBid()、getPrice()、getLevel()等等,而MarketData应该由一个MarketDataProvider通过 依赖注入(dependency injection) 组成。因此,当你修改你的MarketData 提供器(MarketDataProvider)时,调用端不会受影响,因为它们是通过MarketData接口或类的方法来访问的。

  1. 在Java中,为什么不允许从静态方法中访问非静态变量?

你在Java中不能从静态上下文访问非静态数据只是因为非静态变量是跟具体的对象实例关联的,而静态的却没有和任何实例关联。你可以看我的文章为什么在静态上下文中不能访问非静态变量查看详细的讨论。

  1. 在Java中设计一个并发规则的pipeline?

并发编程或并发设计这些天很火,它可以充分利用现在不断提升的高级处理器的处理能力,而Java成为一个多线程语言也从这种情况获益良多。设计一个并发系统需要记住的最关键的点是线程安全,不可变性,本地变量和避免使用static或者类变量(instance variables)。你只需要想着每一类都可以同时被多个线程同时执行,所以最好的做法就是每一个线程都处理自己的数据 ,不跟其他数据交互,并且运行时只需要最小的同步保证。这个问题可以涉及到从最初的讨论到完整的类和接口编码,但只要你记住并发中最重要的点和问题如,竞争条件(race condition)、死锁(deadlock)、内存交互问题(memory interference)、原子性、ThreadLocal变量等,你都可以回答它。

给初学者的设计模式面试问题
这些软件设计和设计模式问题大多在初学者层次时被问起,目的只是了解一下候选人(应聘者)对设计模式知道多少,如, 设计模式是什么 或者 一个特定的设计模式做什么 ?这些问题通过简单地记忆概念就可以回答,但就信息和知识而言还是有价值的。

  1. 什么是设计模式?你是否在你的代码里面使用过任何设计模式?

设计模式是世界上各种各样程序员用来解决特定设计问题的尝试和测试的方法。设计模式是代码可用性的延伸。

  1. 你可以说出几个在JDK库中使用的设计模式吗?

装饰器设计模式(Decorator design pattern)被用于多个Java IO类中。单例模式(Singleton pattern)用于Runtime,Calendar和其他的一些类中。工厂模式(Factory pattern)被用于各种不可变的类如Boolean,像Boolean.valueOf,观察者模式(Observer pattern)被用于Swing和很多的事件监听中。

  1. Java中什么是单例设计模式?用Java写出线程安全的单例

单例模式重点在于在整个系统上共享一些创建时较耗资源的对象。整个应用中只维护一个特定类实例,它被所有组件共同使用。Java.lang.Runtime是单例模式的经典例子。你可以在我的文章Java单例模式的10个问题看到更多的问题和讨论。从Java 5开始你可以使用枚举(enum)来实现线程安全的单例。

  1. 使用工厂模式最主要的好处是什么?你在哪里使用?

工厂模式的最大好处是增加了创建对象时的封装层次。如果 你使用工厂来创建对象,之后你可以使用更高级和更高性能的实现来替换原始的产品实现或类,这不需要在调用层做任何修改。可以看我的文章工厂模式得更详细的解释和和了解更多的好处。

  1. 在Java中,什么叫观察者设计模式(observer design pattern)?

观察者模式是基于对象的状态变化和观察者的通讯,以便他们作出相应的操作。简单的例子就是一个天气系统,当天气变化时必须在展示给公众的视图中进行反映。这个视图对象是一个主体,而不同的视图是观察者。可以在这篇文章中看到Java观察者模式的完整例子。

  1. 举一个用Java实现的装饰模式(decorator design pattern)?它是作用于对象层次还是类层次?

装饰模式增加强了单个对象的能力。Java IO到处都使用了装饰模式,经典的例子就是Buffered系列类如BufferedReader和BufferedWriter,它们增强了Reader和Writer对象,以实现提升性能的Buffer层次的读取和写入。可以看这篇文章了解更多。

  1. 什么是MVC设计模式?举一个MVC设计模式的例子?

8, Java中什么是表示层设计模式(FrontController design pattern)?举一个使用表示层设计模式(front controller pattern)的例子?

  1. 什么是责任链模式(Chain of Responsibility)?

  2. 什么是适配器模式?举用Java实现适配器模式的例子?

这些留给你自己做练习,作为面试准备,试着去找出这些设计模式的答案。

这些是我在很多面试中都看到的设计模式问题,当然,在google面试和各种各样的公司如Amzone、Microsoft等等还有很多重要的专业软件设计问题。如果你遇到一些有趣的值得分享的设计问题,不妨分享出来。

原文链接: javarevisited 翻译: ImportNew.com - 陈 晓舜
译文链接: http://www.importnew.com/12649.html