浅谈几种设计模式

设计模式分类

总体来说设计模式分为三大类:

创建型模式:

单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。

结构型模式:

适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式:

策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

设计模式思维导图

单例模式

单例模式的八种写法

1、饿汉式(静态常量)[可用]

2、饿汉式(静态代码块)[可用]

3、懒汉式(线程不安全)[不可用]

4、懒汉式(线程安全,同步方法)[不推荐用]

5、懒汉式(线程安全,同步代码块)[不可用]

6、双重检查[推荐用]

7、静态内部类[推荐用]

8、枚举[推荐用]

简单工厂

又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一。

简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。

Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。

工厂方法模式

public abstract class AbstractDriverFactory {
  public abstract Animal createDriver();//这个方法是为了它的子类重写它的构造方法
}
public class ZhangFactory extends AbstractDriverFactory {
  @Override
  public Driver createDriver() {
    return new Zhang();//返回一个具体的对象老张。  
  }
}
public static void main(String[] args) {
  ZhangFactory zf = new ZhangFactory();//创建老张的工厂对象
  Driver driver = zf.createDriver();//再调用创建司机的方法
  driver.driveCar();//司机去开车
}

不得不说,工厂方法模式虽然完美符合了ocp开闭原则(Open Closed Principle)原则,但却使整个程序变得很沉重。就拿数据库来说,如果有100个访问数据库的类,那么就要创建100个这个类的工厂。

1.简单工厂模式:最大的优点就是在工厂中就包含了必要的判断,使用时只需要根据客户端的选择来实例化即可,对于客户端使用来说,去除了与具体产品的依赖。而缺点就是违背的ocp原则。假如未来要添加一个新的需求,则需要更改简单工厂中的判断语句。这对代码本身就不利。

2.工厂方法模式:最大的优点就是抽象化了简单工厂模式。再有新的需求进来时,不需要更改工厂的内容,符合了ocp原则。而缺点是每增加一个产品就要新增加一个相应的实例化工厂,增加了额外的开发量。

3.抽象工厂模式:分离了具体的类。不会出现在客户端代码中,易于交换产品系列。而且具体的工厂类只在它初始化的时候才会出现。这使得改变一个应用的具体工厂变得很容易~~缺点是,抽象工厂几乎确定了可以创建的对象的集合。加入新的类型对象就需要扩展其接口,这将涉及到具体工厂及其子类的修改。

三种工厂模式虽然用法各不相同,但它们的最终目的都是一致的----解耦。spring容器就是个大型的抽象工厂,不仅可以创建普通的bean实例,也可以创建bean工厂。

适配器模式

将一个类的接口转换成客户希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作,说白了就是为了挂羊头卖狗肉而专门设计的模式。也就是把一个类的接口变换成客户端所期待的另一种接口。

1 ,类的适配

(1)目标(Target)角色:这就是所期待得到的接口。注意:由于这里讨论的是类适配器模式,因此目标不可以是类。

(2)源(Adapee)角色:现在需要适配的接口。

(3)适配器(Adaper)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。

2, 对象的适配

  对象的适配依赖于对象的组合,而不是类适配中的继承。

还是以手机为例子,每一种机型都自带有从电器,有一天自带充电器坏了,而且市场没有这类型充电器可买了,怎么办?万能充电器就可以解决,这个万能充电器就是适配器。

首先来一个IPhone的充电器类(Adaptee角色):

public class IPhoneCharger {
     public void applePhoneCharge(){
         System.out.println("The iPhone is charging ...");
    }
}

要对这个特殊的充电器进行适配,上个适配的接口(Target角色):

 public interface ChargeAdapter {
   public void phoneCharge();
}

因为适配有两种,所以先进行类的适配示例,创建类的适配器:

public class UniversalCharger extends IPhoneCharger implements ChargeAdapter{
  @Override
    public void phoneCharge() {
        System.out.println("The phone is charging, but which kind of phone it is, who cares ...");
       super.applePhoneCharge();//iphone charging
    }
 }

这就是万能充电器了,我们让它来充个电,测试类准备:

public class AdapterClassTest {
    public static void main(String[] args) {
       ChargeAdapter charger = new UniversalCharger();
        charger.phoneCharge();
    } 
}

测试结果:

The phone is charging, but which kind of phone it is, who cares ... The iPhone is charging ...

以上是类的适配,我们还有种对象的适配方式,创建对象的适配器:

public class UniversalCharger implements ChargeAdapter{
     IPhoneCharger iphoneCharger;
     public UniversalCharger(IPhoneCharger iphoneCharger){
         this.iphoneCharger = iphoneCharger;
     }
     @Override
     public void phoneCharge() {
         System.out.println("The phone is charging, but which kind of phone it is, who cares ...");
         iphoneCharger.applePhoneCharge();    
     }
 }

对象适配器创建完毕,测一下:

public class AdapterObjectTest {
     public static void main(String[] args) {
         IPhoneCharger iphoneCharger = new IPhoneCharger();
         ChargeAdapter charger = new UniversalCharger(iphoneCharger);
        charger.phoneCharge();
     }
}

测试结果:

The phone is charging, but which kind of phone it is, who cares ... The iPhone is charging ...

总结一下:

(1)类的适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。

(2)对象的适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个包装类,持有原类的一个实例,在包装类的方法中,调用实例的方法就行。

推荐阅读:

易懂版设计模式--门面模式

设计模式---命令模式

如何搞定Mybatis 中的 9 种设计模式

一篇搞定---装饰器模式

设计模式-Spring

本文分享自微信公众号 - Java后端技术栈(t-j20120622),作者:一如年少时模样

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-05-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 设计模式---命令模式

    命令模式很好理解,举个例子,司令员下令让士兵干件事情,从整个事情的角度来考虑,司令员的作用是,发出口令,口令经过传递,传到了士兵耳朵里,士兵去执行。这个过程好在...

    用户4143945
  • 【刨根问底】java注解--上

    从JDK1.5开始,Java增加了对元数据的支持,也就是Annotation,首先说明注释和注解不是同一回事,是有区别的。本次分享的注解,其实就是代码里的特色标...

    用户4143945
  • Java多线程实战:多线程方法详解

    从结果可知:Mythread的构造方法是被main线程调用的,而run方法是被名称为Thread-0的线程调用的,run方法是线程自动调用的

    用户4143945
  • 抽象工厂模式(选择产品簇)

    对简单工厂模式还不了解的可以查看下我的历史文章 简单工厂模式,简单工厂模式的核心是使用工厂实现选择创建产品实现,这应该很好理解。

    幺鹿
  • Java多线程开发 - Future的使用与理解

    Future模式是多线程开发中非常常见的一种设计模式。它的核心思想是异步调用。当我们需要调用一个函数方法时。如果这个函数执行很慢,那么我们就要进行等待。但有时候...

    蒋老湿
  • java中的排序(自定义数据排序)--使用Collections的sort方法

        当引用类型的内置排序方式无法满足需求时可以自己实现满足既定要求的排序,有两种方式:

    wfaceboss
  • 复习:GoF的23种设计模式之Strategy模式(行为型)

    上面自己在不同场景三种行为,也可看作整体地替换算法。自己是抽象地,在不同场景实现不同算法。

    营琪
  • Java中泛型的介绍和使用

    我们都知道Java里的集合(list,map....)是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对...

    框架师
  • java之struts2之文件上传

    1.在大多数应用中,都有文件上传功能。有两种文件上传的方式,一种是自己去解析http协议,获取文件上传的内容。另一种是通过第三方插件来实现文件上传。第三方插件一...

    Vincent-yuan
  • 设计模式-责任链模式

    cwl_java

扫码关注云+社区

领取腾讯云代金券