设计模式常见面试题

1.请列举出在JDK中几个常用的设计模式?

单例模式(Singleton pattern)用于Runtime,Calendar和其他的一些类中。工厂模式(Factory pattern)被用于各种不可变的类如 Boolean,像Boolean.valueOf,观察者模式(Observer pattern)被用于 Swing 和很多的事件监听中。装饰器设计模式(Decorator design pattern)被用于多个 Java IO 类中。
 ———————————————— 
版权声明:本文为CSDN博主「妮妮xie」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ninixie/article/details/52824073

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

一句话总结:一个类在Java虚拟机中只有一个对象,并提供一个全局访问点。

生活中例子:太阳、月亮、国家主席等。

单例模式很常用,比如全局缓存、全局状态管理等等这些只需要一个对象,就可以使用单例模式;

解决什么问题:对象的唯一性,性能浪费太多。

项目里面怎么用:数据库连接对象,属性配置文件的读取对象。

//一个很好的单例模式
public class DesignModel1 {
    private static volatile DesignModel1 instance;
    //把构造器私有化
    private DesignModel1(){};

    public static DesignModel1 getInstance() {
        if(instance ==null) {
            synchronized (DesignModel1.class) {
                if(instance==null) {
                    instance = new DesignModel1();
                }
            }
        }
        return instance;
    }
}

单例模式的优缺点

优点:由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能。
缺点:由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。
 

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

一句话总结:用一个方法来代替new关键字

生活中的例子:制衣厂、面包厂等生产厂。

解决什么问题:对象产生过多,或者经常有子类替换生成。

项目里面怎么用:对于经常生成的对象,或者父子类替换的对象。

模式结构:写一个对外声明的方法,方法里面使用new关键字代替。

框架里面使用:spring的核心就是工厂模式。

JDK里面使用:newInstance。

interface Animal{
    public void say();
}

class   Cat implements Animal{
    @Override
    public void say() {
        System.out.println("I am a cat");
    }
    
}

class Dog implements Animal{

    @Override
    public void say() {
        System.out.println("I am a dog");
    }
    
}

class Factory{
    public static Animal getInstance(String className) {
        //通过equal方法在确定类的实例
        Animal ani = null;
        if("cat".equals(className)) {
            ani = new Cat();
        }
        if("dog".equals(className)) {
            ani = new Dog();
        }
        return ani;
    }
}

public class DesignModel2 {
    public static void main(String[] args) {   
        Animal a = null; // 定义接口对象  
        a = Factory.getInstance(args[0]); // 通过工厂获取实例  
        if (a != null) { // 判断对象是否为空  
            a.say(); // 调用方法   
        }   
    } 
}

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

一句话总结:为其他对象提供一个代理,以控制对当前对象的访问。

生活中的例子:房屋中介、婚姻介绍所。

解决什么问题:不能直接访问该对象,或者太大的资源耗费多。

项目里面怎么用:权限,或者大对象的访问权限。

模式结构:代理类和被代理类实现同一个接口,用户访问的时候先访问代理对象,然后让代理对象去访问被代理对象。

框架里面使用:Spring里面的AOP实现。

JDK里面使用:java.lang.reflect.Proxy。

/**
 * 代理模式就是多一个代理类出来,替原对象进行一些操作
 * 例如买房子找中介,上法院找律师等等
 */

 interface Sourceable1 {  
    public void method();  
}  

 class Source1 implements Sourceable {  
      
    @Override  
    public void method() {  
        System.out.println("the original method!");  
    }  
} 
 //注意装饰器模式持有的是接口的实例,代理模式持有的是实现类的实例
 class Proxy1 implements Sourceable1{
     private Source1 source1;

    public Proxy1() {
        super();
        this.source1 = new Source1();
    }
    //重写Sourceable1的method()方法,并且持有的Source1实现类是实例也进行操作
    @Override
    public void method() {
        before();
        source1.method();
        after();
    }
    private void before() {  
        System.out.println("before proxy!");  
    }  
    private void after() {  
        System.out.println("after proxy!");  
    }  
 }
 
 
public class DesignModel7 {
    public static void main(String[] args) {
        Sourceable1 source = new Proxy1();
        source.method(); 
    }
}

(4)适配器模式

一句话总结:将两个原来不兼容的类兼容起来一起工作。

生活中的例子:变压器、充电器

解决什么问题:已经存在的相同功能的代码,但是接口不兼容,不能直接调用。

项目里面怎么用:在使用旧的API的时候,没有源码,和新的不能兼容。

模式结构:分为类适配器和对象适配,一般常用的就是对象适配器,因为组合由于继承。

框架里面使用:单元测试里面的asserEquels。

JDK里面使用:java.util.Arrays#asListjava.io.InputStreamReader(InputStream) java.io.outputStreamWriter(OutputStream)。

/**
 *适配器模式:一个接口可能有多个的实现方法,但是我们不需继承一个接口全部的实现它
 *而是用一个抽象类继承接口,然后我们选择性的继承即可 
 *
 */
interface Window {// 定义Window窗口接口,表示窗口操作  
    public void open();// 窗口打开  
  
    public void close();// 窗口关闭  
  
    public void iconified();// 窗口最小化  
  
    public void deiconified();// 窗口恢复  
  
    public void activated();// 窗口活动  
}   

//定义抽象类实现接口,在此类中覆写方法,但是所有的方法体为空   
abstract class WindowAdapter implements Window {   
 public void open() {   
 };// 窗口打开   

 public void close() {   
 };// 窗口关闭   

 public void iconified() {   
 };// 窗口最小化   

 public void deiconified() {   
 };// 窗口恢复   

 public void activated() {   
 };// 窗口活动   
}   

//子类继承WindowAdapter抽象类,选择性实现需要的方法   
class WindowImpl extends WindowAdapter {   
 public void open() {   
     System.out.println("窗口打开");// 实现open()方法  
 }   

 public void close() {   
     System.out.println("窗口关闭");// 实现close()方法  
 }   
}   
public class DesignModel4 {
    public static void main(String args[]) {   
        Window win = new WindowImpl(); // 实现接口对象  
        // 调用方法   
        win.open();   
        win.close();   
    }  
}

(5)构造者模式

/**
 * 
 *构造者模式
 */

interface Sender {  
    public void Send();  
}  

class MailSender implements Sender {  
    @Override  
    public void Send() {  
        System.out.println("this is mailsender!");  
    }  
}  

class SmsSender implements Sender { 
      
    @Override  
    public void Send() {  
        System.out.println("this is sms sender!");  
    }  
}  

//MailSender和SmsSender为Sender的接口实现类,所以可以在list中加入
//DesignModel5一个类管理着多个对象的实例
public class DesignModel5 {
    private List list = new ArrayList();  
    
    public void produceMailSender(int count){  
        for(int i=0; i

(6)装饰模式

//装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例
interface Sourceable {  
    public void method();  
}  

//本来Source方法继承了Sourceable实现了method()方法
class Source implements Sourceable {  
      
    @Override  
    public void method() {  
        System.out.println("the original method!");  
    }  
}  

//Decorator持有Sourceable的属性,对其进行装饰
class Decorator implements Sourceable {  
      
    private Sourceable source;  
      
    public Decorator(Sourceable source){  
        super();  
        this.source = source;  
    }  
    @Override  
    public void method() {  
        System.out.println("before decorator!");  
        source.method();  
        System.out.println("after decorator!");  
    }  
}  
public class DesignModel6 {
    public static void main(String[] args) {  
        //接口不能单独的实例化,必须通过实现类来帮助实例化
        Sourceable source = new Source();  
        Sourceable obj = new Decorator(source);  
        obj.method();  
    }  
}

(7)观察者模式

interface Observer{
    public void updata();
}

class Observer1 implements Observer{

    @Override
    public void updata() {
        System.out.println("observer1 has received!");  
    }
    
}

class Observer2 implements Observer{

    @Override
    public void updata() {
        System.out.println("observer2 has received!");  
    }
    
}

interface Subject{
     /*增加观察者*/  
    public void add(Observer observer);
     /*删除观察者*/  
    public void del(Observer observer);
     /*通知所有的观察者*/  
    public void notifyObservers();
    /*自身的操作*/  
    public void operation();
}

abstract class AbstractSubject implements Subject{
    private List observers = new ArrayList<>();

    @Override
    public void add(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void del(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        Iterator ite = observers.iterator();
        while(ite.hasNext()) {
            ite.next().updata();
        }
    }
    
    
    
}

class MySubject extends AbstractSubject{

    @Override
    public void operation() {
        System.out.println("udpate self");
        notifyObservers();
    }
    
}



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



作者:林子康better
链接:https://www.jianshu.com/p/77fcd3e8f9f7
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

. 举例说明你什么时候会用抽象类,什么时候更愿意使用接口?

 

  • 抽象类是一种模板,而接口是一种规范
  • 在Java中,你只能继承一个类,但实现多个接口。所以你继承一个类的时候就无法再继承别的类了。
  • 接口是用来代表形容词或行为,例如Runnable、Clonable、Serializable等。因此,如果您使用一个抽象类来实现Runnable和Clonacle,你就不可以使你的类同时实现这两个功能,而如果接口的话就没问题。
  • 抽象类是比接口稍快,所以很在乎时间的应用尽量使用抽象类。
  • 如果多个继承层次的共同行为在在同一个地方编写更好,那么抽象类会是更好的选择。有时候可以在接口里定义函数但是在抽象类里默认功能就能实现接口和抽象类共同工作了。

Template(模板模式)

一句话总结:父类定义流程,子类实现流程。

生活中的例子:iphone生产有多个国家,但流程只有一个。

解决什么问题:业务有多种,但都有规定的流程。

项目里面怎么用:一般基类的实现都是模板模式,BaseDAO,bBaseService。

模式结构:定义一个抽象父类定义流程,或者常用方法和常量,子类继承父类,实现具体的细节方法。

框架里面使用:hibernate里面的方言,是跨数据库的基础。

JDK里面使用:IO流里面的InputStream,Writer等。

 

模板模式代码:

//定义一个父类,定义流程

 

[java] view plain copy

  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

 

[java] view plain copy

  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

 

[java] view plain copy

  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. }  

你可能感兴趣的:(设计模式)