常用设计模式介绍

java设计模式类型

  • 创建型模式:将对象的创建与使用分离

  • 结构型模式:如何将类和对象按照某种布局组成更大的格局

  • 行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务

23种设计模式介绍

1.单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局

访问点供外部获取该实例,其拓展是有限多例模式。

2.原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆

出多个和原型类似的新实例。

3.工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子

类决定生产什么产品。

4.抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个

子类可以生产一系列相关的产品。

5.建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然

后根据不同需要分别创建它们,最后构建成该复杂对象。

6.代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客

户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。

7.适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,

使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

8.桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。它是用组

合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

9.装饰(Decorator)模式:动态的给对象增加一些职责,即增加其额外的功

能。

10. 外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子

系统更加容易被访问。

11. 享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复

用。

12. 组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象

和组合对象具有一致的访问性。

13. 模板方法(TemplateMethod)模式:定义一个操作中的算法骨架,而将算

法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定

义该算法的某些特定步骤。

14. 策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它

们可以相互替换,且算法的改变不会影响使用算法的客户。

15. 命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任

和执行请求的责任分割开。

16. 职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下

一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。

17. 状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能

力。

18. 观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改

变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。

19. 中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互

关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。

20. 迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数

据,而不暴露聚合对象的内部表示。

21. 访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个

元素提供多种访问方式,即每个元素有多个访问者对象访问。

22. 备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对

象的内部状态,以便以后恢复它。

23. 解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的

解释方法,即解释器

常用设计模式:

单例模式

定义:在有些系统中,为了节省内存资源、保证数据内容的一致性,创建一个实例共大家享用,例如:Runtime类

特点

  • 单例只有一个实例对象

  • 该单例对象必须由单例类自行创建

  • 单例;类对外提供一个公共的方法进行访问

  1. 饿汉模式

在这里拿window为例给大家进行演示

public class Window {
    /*饿汉式单例:在类加载的时候的初始化实例(static)
    * 因为创建的实例只有一个,所以不存在线程安全问题*/
    private static Window window=new Window();

    public Window getWindow(){
             return window;
    }
}
public class Test {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                System.out.println(new Window().getWindow());//获得是同一个对象
            }).start();
        }
    }
}
  1. 懒汉模式

public class Window {
    /*懒汉式单例:
    * 在类加载的时候,不创建对象,在使用时进行创建
    * 这时,生成对象的数量就需要我们自己来进行控制
    * 但是懒汉式单例会出现线程安全问题:在多线程访问时,可能会有多个线程同时进行到if中,就会创建出多个对象
    * 在并发的时候,会出现指令重排的情况,所以用volatile防止指令重排,避免造成错误*/
   
    private static volatile Window window;
    public Window getWindow(){
        try {
            //增加休眠增加并发的几率
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
          //1.0版本给方法上锁,虽然可行,但是效率太低,每次只能运行一个线程
          // if(windows==null){  1.1版本 进入if之后上锁,这种上锁起不到多个线程公用一个对象实例的作用,一个执行完之后,另外一个线程进入重新创建一个实例对象
          // synchronized (Windows.class){
          // window=new Window()}
//}
        //最终版本,双重判断,公用一个对象实例
        if(window==null){
            synchronized (Window.class){
                if (window==null){
                    window=new Window();
                }

            }
        }
        return window;
    }
}
public class Test {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                System.out.println(new Window().getWindow());
            }).start();
        }
    }
}

工厂模式

  1. 简单工厂:适用于产品子类较少,不符合开闭原则

模式中包含的角色及其职责

工厂:负责逻辑运算以及创建所需要的产品

抽象产品:描述所有实例共有的接口或者是抽象类

具体产品抽象:是简单工厂的创建目标

代码实现:

//Car接口
public interface Car {

      void run();
}
//CarFactory工厂类
public class CarFactory{
     public static Car createCar(String name){
            if(name.equals("aodi")){
                return new Aodi();
            }
            if(name.equals("bmw")){
                return new Bmw();
            }
            return null;
     }
}
//实现类
public class Aodi implements Car{

    @Override
    public void run() {
        System.out.println("奥迪汽车行驶");
    }
}
//实现类
public class Bmw implements Car{

    @Override
    public void run() {
        System.out.println("宝马汽车行驶");
    }

}
//客户端
public class Test {

    public static void main(String[] args) {
  //每次增加子类类型的时候,需要对代码进行修改,不符合开闭原则,适用于子类较少或者是不容易修改的项目中
  //优点:客户端不负责对象的创建,由专门的工厂进行创建,客户端直需要对对象进行调用,实现创建和调用的分离,降低了代码的耦合度
  //缺点:如果增加或减少子类,需要对代码进行修改,违背了设计原则中的开闭原则,如果子类过多,会导致工厂非常庞大,违背了高内聚原则,不利于后期的维护
        Car bmw  = CarFactory.createCar("bmw");
        Car aodi  = CarFactory.createCar("aodi");

          bmw.run();
          aodi.run();
    }
}
  1. 工厂方式模式

对工厂也进行了抽象,将实际创建工作推迟到子类去完成

优点:客户端不负责创建对象的创建,而是由专门的工厂类完成,客户端只负责对象的调用,实现了创建和调用的分离,降低了客户端代码的难度,若增加和减少产品子类,不需要对工厂进行修改,直需要增加产品子类和工厂子类,符合开闭原则,即使产品子类过多也不会导致工厂类的庞大,利于后期的维护

缺点:需要些额外的代码,增加了工作量

抽象工厂模式

将同一品牌的物品放在一起进行生产,就好比你去生产联的大厂中既可以买到联想手机也可以买到联想电脑,不用将它们分别生产,造成资源浪费

优点:获取具体系列产品只需要通过具体的系列的工厂获取,无心关心创建的细节

原型模式:

在项目中,我们需要很多个实例,但是创建实例对象又很麻烦,所以觉得直接创建对象是一个不太明智的选择,所以我们经常在需要多次创建相同的对象的时候用到克隆(clone),为了提高创建速度

代理模式:

代理模式就是给一个对象提供一个代理,并由代理对象控制对原对象的引用,使得客户不能直接与真正的目标对象通信,代理对象是对象的代表,客户端通过代理对象对实际对象进行操作

  • 静态代理

特点:代理类实现一个接口,任何实现给接口的对象,都可以通过代理类进行代理,增加了通用性

优点:可以做到在符合开闭原则的情况下对目标对象进行功能扩展

缺点:代码量大,必须要有接口,再有代理

//Computer对象类
public class Compurter implements Huawei{

    @Override
    public void run() {
        System.out.println("华为电脑跑步机器");
    }

    @Override
    public void play() {
        System.out.println("华为电脑在玩");
    }
}
//customer客户端
public class customer {

    public static void main(String[] args) {
        Phone phone=new Phone();
        Compurter compurter=new Compurter();

        Proxy proxy1=new Proxy(phone);
        Proxy proxy=new Proxy(compurter);
        proxy.play();
        proxy1.run();
    }

}
//Huawei接口
public interface Huawei {
    public void run();
    public void play();
}
//Phone对象类
public class Phone implements Huawei{
    @Override
    public void run() {
        System.out.println("华为手机在跑步");
    }

    @Override
    public void play() {
        System.out.println("华为手机在玩");
    }


}
//Proxy代理对象
public class Proxy implements Huawei {
   Huawei huawei;

     public Proxy(Huawei huawei){
        this.huawei=huawei;
     }
    @Override
    public void run() {
            try {
                System.out.println("你是大坏蛋");
            } catch (Exception e) {

            } finally {
                System.out.println("终于完了");
            }


    }

    @Override
    public void play() {
       huawei.play();
    }
}
  • 动态代理

通过动态代理我们就不需要手动的创建代理类了,只需要编写一个动态处理就可以了,代理对象通过动态处理

jdk动态代理:

public class JdkProxy implements InvocationHandler {

    Object object;//真实对象,接收任何的目标类对象

    public JdkProxy(Object object){
        this.object=object;
    }
    /* 在动态代理类中调用目标类中的具体方法,动态的将代理对象对象
    * 目标类中要调用方法,以及方法中的参数传递过来
    *  Method method  动态获取的真正要执行的方法*/
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        method.invoke(object);
        return proxy;
    }

    //真正意义上的运行时生成代理对象
    public Object getProxy(){
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(),this);
    }
}

cg动态代理:

/*
 * 动态代理类
 */
public class CGLibProxy implements MethodInterceptor {
    
        private Enhancer enhancer = new Enhancer();
        
        public Object getProxy(Class<?> clazz){  
            enhancer.setSuperclass(clazz);  
            enhancer.setCallback(this);  
            return enhancer.create();  
        }  
        /*
         * 拦截所有目标类方法的调用 
         * 参数: 
         * obj  目标实例对象 
         * method 目标方法的反射对象 
         * args 方法的参数 
         * proxy 代理类的实例 
         */  
        public Object intercept(Object obj, Method method, Object[] args,  
                MethodProxy proxy) throws Throwable {
            //代理类调用父类的方法  
            System.out.println("开始事务");  
            Object obj1 = proxy.invokeSuper(obj, args);  
            System.out.println("关闭事务");  
            return obj1;  
        }
}

猜你喜欢

转载自blog.csdn.net/dfdbb6b/article/details/129018601