Java常用设计模式——工厂模式、单例模式、观察者模式、代理模式、外观模式

一.设计模式分类

1) 建设型模式
工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式
2) 结构型模式
适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式
3) 行为型模式
策略模式,模板方法模式,观察者模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,中介者模式,解释器模式

二.设计模式六大原则

1) 开闭原则
开闭原则就是对于扩展开放,对于修改关闭。在程序需要进行扩展时,不能去修改原有的代码,实现一个热插拔的效果

2)里氏代换原则

  1. 子类的能力必须大于等于父类的能力,即父类可以使用的方法,子类都可以使用。
  2. 返回值同理,假设父类方法返回一个 List ,那么子类应该返回一个 ArrayList 。如果父类返回一个 ArrayList,子类返回一个 List是不可以的,这时子类返回值的能力比父类小。
  3. 抛出异常情况同理,任何子类方法可以声明抛出父类方法声明异常的子类,而不能声明父类没有声明的异常。

3)依赖倒转原则
这是开闭原则的基础,即面向接口编程,依赖于抽象而不是依赖于具体实例。

4)接口隔离原则
使用多个隔离的接口,比使用单个接口要好,而且可以降低类之间的耦合度。即降低依赖,降低耦合。

5)迪米特法则(最少知道原则)
一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

6)合成复用原则
尽量使用合成/聚合的方式,而不是使用继承。

三.常见设计模式

工厂方法模式

    现在需要创建几个对象,且这几个对象有共同的特征(实现了同一个接口的一些类),则不需要具体创建各个对象,而是创建对象的工厂类,通过工厂类实现对象的创建。

public interface Sender {  
    public void Send();  
}  

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

public class SmsSender implements Sender {  

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

public class SendFactory {  

    public static Sender produceMail(){  
        return new MailSender();  
    }  

    public static Sender produceSms(){  
        return new SmsSender();  
    }  
}  

public class FactoryTest {  

    public static void main(String[] args) {      
        Sender sender = SendFactory.produceMail();  
        sender.Send();  
    }  
}  

抽象工厂模式

    工厂方法模式有一个问题就是:类的创建依赖工厂类,对于程序的扩展(添加一个新的对象),就必须对工厂类进行修改,这违背了开闭原则。但是抽象工厂模式可以很好的解决上述问题。

public interface Provider {  
    public Sender produce();  
}  

public class SendMailFactory implements Provider {  

    @Override  
    public Sender produce(){  
        return new MailSender();  
    }  
}  


public class SendSmsFactory implements Provider{  

    @Override  
    public Sender produce() {  
        return new SmsSender();  
    }  
}  

public class Test {  

    public static void main(String[] args) {  
        Provider provider = new SendMailFactory();  
        Sender sender = provider.produce();  
        sender.Send();  
    }  
}  

    如果要发送微信,则只需要增加一个微信的实现类,实现 Sender 接口,同时增加一个相应的工厂类,实现Provider 接口就可以了,无须对现有代码进行修改,不违背开闭原则同时扩展性良好。

单例模式

    确保某个类只有一个实例,并且自行实例化并向整个程序提供这个实例。

public class SingleObject {

   //创建 SingleObject 的一个对象
   private static SingleObject instance = new SingleObject();

   //让构造函数为 private,这样该类就不会被实例化
   private SingleObject(){}

   //获取唯一可用的对象
   public static SingleObject getInstance(){
      return instance;
   }

}
单例写法分类
单例写法单例保障机制单例对象初始化时机优点缺点
饿汉模式类加载机制类加载简单,易理解难以保证懒加载,无法应对反射和反序列化
双重校验锁(DCL)锁机制(避免 volatile 重排序)第一次调用 getInstance()实现懒加载复杂,无法应对反射和反序列化
Holder模式(静态内部类)类加载机制第一次调用 getInstance()实现懒加载无法应对反射和反序列化
枚举枚举语言特征第一次引用枚举对象简单,安全(语言级别防止通过反射和反序列化破坏单例)enum的另类用法
参考

单例的四种写法以及三种保护手段

观察者模式

    一个对象(subject)被其他多个对象(observer)所依赖,当一个对象变化时发出通知,其他依赖于该对象的对象都会收到通知,并且随着一起变化。比如声音报警器和闪光灯报警器分别监察热水器温度,当热水器温度过高时发出通知,两个报警器分别发声,闪光以及报警。

public interface Observer {  
    public void update();  
}  

public class Observer1 implements Observer {  

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

public class Observer2 implements Observer {  

    @Override  
    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>();  
    @Override  
    public void add(Observer observer) {  
        vector.add(observer);  
    }  

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

    @Override  
    public void notifyObservers() {  
        Enumeration<Observer> enumo = vector.elements();  
        while(enumo.hasMoreElements()){  
            enumo.nextElement().update();  
        }  
    }  

public class MySubject extends AbstractSubject {  

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

}  

public class ObserverTest {  

    public static void main(String[] args) {  
        Subject sub = new MySubject();  
        sub.add(new Observer1());  //订阅这个对象
        sub.add(new Observer2());  

        sub.operation();  //发出改变的一个通知
    }  

}  

代理模式

    一个代理类代表了一个真实类的功能,通过访问代理类来实现对真实类的访问,增强了对于真实类的保护。比如需要对原有的方法进行修改,就是采用一个代理类调用原有的方法进行修改,避免修改原有的代码。

interface Subject {
    void request();
}

class RealSubject implements Subject {
    public void request(){
        System.out.println("RealSubject");
    }
}

class Proxy implements Subject {
    private Subject subject;

    public Proxy(Subject subject){
        this.subject = subject;
    }
    public void request(){
        System.out.println("begin");
        subject.request();
        System.out.println("end");
    }
}

public class ProxyTest {
    public static void main(String args[]) {
        RealSubject subject = new RealSubject();
        Proxy p = new Proxy(subject);
        p.request();
    }
}

外观模式

    外观模式同工厂方法模式类似,也是要创建多个有共同特征的对象(多个类实现同一个接口),但是工厂方法模式对象的创建是并行的,而外观模式对象的创建是有先后顺序的,是串行的,需要使用组合。

public class Computer {  
//是组合,而非继承。这是与工厂模式的显著区别。
    private CPU cpu;  
    private Memory memory;  
    private Disk disk;  

    public Computer(){  
        cpu = new CPU();  
        memory = new Memory();  
        disk = new Disk();  
    }  

    public void startup(){  
        System.out.println("start the computer!");  
        cpu.startup();  
        memory.startup();  
        disk.startup();  
        System.out.println("start computer finished!");  
    }  

    public void shutdown(){  
        System.out.println("begin to close the computer!");  
        cpu.shutdown();  
        memory.shutdown();  
        disk.shutdown();  
        System.out.println("computer closed!");  
    }  
}  

public class User {  

    public static void main(String[] args) {  
        Computer computer = new Computer();  
        //将计算机的启动过程封装成一个类
        computer.startup();  
        computer.shutdown();  
    }  
}  
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值