常见设计模式


设计模式的目的: 将易变的事物与不变的事物分开,隔离代码中的更改。

单例模式

  • 定义:
    单例模式确保某个类中只有一个实例,而且自行实例化并向整个系统提供这个实例。(对于多个对象使用同一个配置信息时,就需要保证该对象的唯一性)

  • 特点:
    单例类只能有一个实例
    单例类必须自己创建自己的唯一实例
    单例类必须给其他对象提供这一实例

  • 单例模式的实现:

/**
 * 描述:     双重检查(推荐面试使用)
 */
public class Singleton6 {
	//volatile的使用
    private volatile static Singleton6 instance;

    private Singleton6() {

    }

    public static Singleton6 getInstance() {
        if (instance == null) {
            synchronized (Singleton6.class) {
            //二次判断,确保此时真正还没有实例创建
                if (instance == null) {
                    instance = new Singleton6();
                }
            }
        }
        return instance;
    }
}

单例模式的几种实现方式

  • 应用:
    计算机系统、线程池、缓存、日志对象等对象常被设计成单例

    • JDK 源码中的 Runtime 类部分源码

//饿汉式单例设计模式
public class Runtime {
    private static Runtime currentRuntime = new Runtime();
 
    public static Runtime getRuntime() {
        return currentRuntime;
    }
 
    private Runtime() {
    }
 
    //...

工厂模式

  • 定义:
    提供了一种创建对象的最佳方式,在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过一个共同的接口来指向新创建的对象。(创建型模式

  • 分类:

    • 简单工厂模式(不标准)
    • 工厂方法模式
    • 抽象工厂模式
  • 创建型模式优点:

    • 对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离。
    • 为了使软件的结构更加清晰,外界对于这些对象的只需要知道题他们共同的接口,而不清楚具体的实现细节,使整个系统的设计更加符合单一职责原则。
    • 隐藏了类的实例的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的。
  • 工厂模式优点:

    • 可以使代码结构清晰,有效地封装变化。在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产品。
    • 对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。
    • 降低耦合度。产品类的实例化通常来说是很复杂的,它需要依赖很多的类,而这些类对于调用者来说根本无需知道,如果使用了工厂方法,我们需要做的仅仅是实例化好产品类,然后交给调用者使用。对调用者来说,产品所依赖的类都是透明的。
    • 在任何需要生成复杂对象的地方,都可以使用工厂方法模式
  • 代码实现

//简单工厂模式
// 抽象产品类
abstract class Car {
   public void run();

   public void stop();
}

// 具体实现类
class Benz implements Car {
   public void run() {
       System.out.println("Benz开始启动了。。。。。");
   }

   public void stop() {
       System.out.println("Benz停车了。。。。。");
   }
}

class Ford implements Car {
   public void run() {
       System.out.println("Ford开始启动了。。。");
   }

   public void stop() {
       System.out.println("Ford停车了。。。。");
   }
}

// 工厂类
class Factory {
   public static Car getCarInstance(String type) {
       Car c = null;
       if ("Benz".equals(type)) {
           c = new Benz();
       }
       if ("Ford".equals(type)) {
           c = new Ford();
       }
       return c;
   }
}

public class Test {

   public static void main(String[] args) {
       Car c = Factory.getCarInstance("Benz");
       if (c != null) {
           c.run();
           c.stop();
       } else {
           System.out.println("造不了这种汽车。。。");
       }

   }

}
//工厂模式
// 抽象产品角色
public interface Moveable {
   void run();
}

// 具体产品角色
public class Plane implements Moveable {
   @Override
   public void run() {
       System.out.println("plane....");
   }
}

public class Broom implements Moveable {
   @Override
   public void run() {
       System.out.println("broom.....");
   }
}

// 抽象工厂
public abstract class VehicleFactory {
   abstract Moveable create();
}

// 具体工厂
public class PlaneFactory extends VehicleFactory {
   public Moveable create() {
       return new Plane();
   }
}

public class BroomFactory extends VehicleFactory {
   public Moveable create() {
       return new Broom();
   }
}

// 测试类
public class Test {
   public static void main(String[] args) {
       VehicleFactory factory = new BroomFactory();
       Moveable m = factory.create();
       m.run();
   }
}
//抽象工厂类
public abstract class AbstractFactory {
   public abstract Vehicle createVehicle();
   public abstract Weapon createWeapon();
   public abstract Food createFood();
}
//具体工厂类,其中Food,Vehicle,Weapon是抽象类,
public class DefaultFactory extends AbstractFactory{
   @Override
   public Food createFood() {
       return new Apple();
   }
   @Override
   public Vehicle createVehicle() {
       return new Car();
   }
   @Override
   public Weapon createWeapon() {
       return new AK47();
   }
}
//测试类
public class Test {
   public static void main(String[] args) {
       AbstractFactory f = new DefaultFactory();
       Vehicle v = f.createVehicle();
       v.run();
       Weapon w = f.createWeapon();
       w.shoot();
       Food a = f.createFood();
       a.printName();
   }
}

代码参考
参考文章1
参考文章2

  • Spring IOC 容器底层实现:工厂+反射+配置文件

策略模式

  • 定义:

    • 策略模式是对算法的包装,把使用算法的责任和算法本身分隔开,委派给不同的对象管理。
    • 通常把一系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类
    • 策略模式定义了一些列的算法,并将每一个算法封装起来,而且使他们可以相互替换,让算法独立于使用他们的客户而独立变化
  • 代码演示

创建接口

public interface Strategy {
   public int doOperation(int num1, int num2);
}

创建接口实现类

//定义实现接口的不同类
//多种实现方式
//实现类一
public class OperationAdd implements Strategy{

	//重写原接口方法,使用两个 int 数相加
   @Override
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}

//实现类二
public class OperationSubstract implements Strategy{

	//重写原接口方法,使用两个 int 数相减
   @Override
   public int doOperation(int num1, int num2) {
      return num1 - num2;
   }
}

创建 Context 类


//策略执行
public class Context {
   private Strategy strategy;

   public Context(Strategy strategy){
      this.strategy = strategy;
   }

   public int executeStrategy(int num1, int num2){
      return strategy.doOperation(num1, num2);
   }
}

测试

//使用 Context 来查看当它改变策略时 Strategy时的行为变化
public class StrategyPatternDemo {
   public static void main(String[] args) {
      Context context = new Context(new OperationAdd());    
      System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
      context = new Context(new OperationSubstract());      
      System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
}

//运行结果
//10 + 5 = 15
//10 - 5 = 5

责任链模式

  • 定义:

    • 为请求创建一个接收者对象的链
    • 避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止
    • 职责链上的处理者负责处理请求,客户只需要将请求发送到责任链上即可,无需关心请求的处理细节和请求的传递
    • 降低耦合度。它将请求的发送者和接收者解耦 。简化了对象,使得对象不需要知道链的结构
  • 案例
    场景

    • 现实中,请假的OA申请,请假天数如果是半天到1天,可能直接主管批准即可;
    • 如果是1到3天的假期,需要部门经理批准;
    • 如果是3天到30天,则需要总经理审批;
      大于30天,正常不会批准。

    为了实现上述场景,我们可以采用责任链设计模式案例及参考代码

  • 缺点

    • 不能保证请求一定被接收
    • 系统性能将受到一定影响,调试时不方便,可能会造成循环调用
  • 应用场景

    • 有多个对象可以处理一个请求,由哪个对象处理请求由运行时刻自动确定
    • 可动态指定一组对象处理请求,或添加新的处理者
    • 在不明确指定处理者的情况下,向多个处理者中的一个提交请求
    • Spring 拦截器链、servlet 过滤器链等都采用了责任链设计模式:代码参考
  • 总结

    • 责任链主要重在责任分离处理,让各个节点各司其职
    • 责任链上的各个节点都有机会处理事务,但是也可能都不受理请求
    • 责任链较长时,调试可能较麻烦
    • 责任链一般用于处理流程节点之类的实际业务场景中

观察者模式

  • 定义:对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
  • 参考例子
    假设有三个人,小美(女,22),小王和小李。小美很漂亮,小王和小李是两个程序猿,时刻关注着小美的一举一动。有一天,小美说了一句:“谁来陪我打游戏啊。”这句话被小王和小李听到了,结果乐坏了,蹭蹭蹭,没一会儿,小王就冲到小美家门口了,在这里,小美是被观察者,小王和小李是观察者,被观察者发出一条信息,然后观察者们进行相应的处理
public interface Person {
   //小王和小李通过这个接口可以接收到小美发过来的消息
   void getMessage(String s);
}
public class LaoWang implements Person {

   private String name = "小王";

   public LaoWang() {
   }

   @Override
   public void getMessage(String s) {
       System.out.println(name + "接到了小美打过来的电话,电话内容是:" + s);
   }

}

public class LaoLi implements Person {

   private String name = "小李";

   public LaoLi() {
   }

   @Override
   public void getMessage(String s) {
       System.out.println(name + "接到了小美打过来的电话,电话内容是:->" + s);
   }

}
public class XiaoMei {
   List<Person> list = new ArrayList<Person>();
    public XiaoMei(){
    }

    public void addPerson(Person person){
        list.add(person);
    }

    //遍历list,把自己的通知发送给所有暗恋自己的人
    public void notifyPerson() {
        for(Person person:list){
            person.getMessage("你们过来吧,谁先过来谁就能陪我一起玩儿游戏!");
        }
    }
}
public class Test {
   public static void main(String[] args) {

       XiaoMei xiao_mei = new XiaoMei();
       LaoWang lao_wang = new LaoWang();
       LaoLi lao_li = new LaoLi();

       //小王和小李在小美那里都注册了一下
       xiao_mei.addPerson(lao_wang);
       xiao_mei.addPerson(lao_li);

       //小美向小王和小李发送通知
       xiao_mei.notifyPerson();
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值