什么是设计模式

设计模式,是一套被重复应用、少数人通晓的、通过分类编目标、代码设计教训的总结。应用设计模式是为了可重用代码、让代码更容易被别人了解、保障代码可靠性、程序的重用性。

为什么要学习设计模式

设计模式的实质是面向对象设计准则的理论使用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充沛了解

  • 能够进步程序员的思维能力、编程能力和设计能力。
  • 使程序设计更加标准化、代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期。
  • 使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。

设计模式分类

大体能够分为三种,每种加起又能够细分为23种。

  • 创立型模式,共五种:工厂办法模式、形象工厂模式、单例模式、建造者模式、原型模式。
  • 结构型模式,共七种:适配器模式、装璜器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  • 行为型模式,共十一种:策略模式、模板办法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

设计模式的六大准则

凋谢关闭准则

  • 准则思维:尽量通过扩大软件实体来解决需要变动,而不是通过批改已有的代码来实现变动
  • 形容:一个软件产品在生命周期内,都会发生变化,既然变动是一个既定的事实,咱们就应该在设计的时候尽量适应这些变动,以进步我的项目的稳定性和灵活性。
  • 长处:繁多准则通知咱们,每个类都有本人负责的职责,里氏替换准则不能毁坏继承关系的体系。

里氏代换准则

  • 准则思维:应用的基类能够在任何中央应用继承的子类,完满的替换基类。
  • 大略意思是:子类能够扩大父类的性能,但不能扭转父类原有的性能。子类能够实现父类的形象办法,但不能笼罩父类的非形象办法,子类中能够减少本人特有的办法。
  • 长处:减少程序的健壮性,即便减少了子类,原有的子类还能够持续运行,互不影响。

依赖倒转准则

  • 依赖倒置准则的核心思想是面向接口编程.
  • 依赖倒转准则要求咱们在程序代码中传递参数时或在关联关系中,尽量援用档次高的形象层类,
  • 这个是凋谢关闭准则的根底,具体内容是:对接口编程,依赖于形象而不依赖于具体。

接口隔离准则

  • 这个准则的意思是:应用多个隔离的接口,比应用单个接口要好。还是一个升高类之间的耦合度的意思,从这儿咱们看出,其实设计模式就是一个软件的设计思维,从大型软件架构登程,为了降级和保护不便。所以上文中屡次呈现:升高依赖,升高耦合。
  • 例如:领取类的接口和订单类的接口,须要把这俩个类别的接口变成俩个隔离的接口

迪米特法令(起码晓得准则)

  • 准则思维:一个对象该当对其余对象有尽可能少地理解,简称类间解耦
  • 大略意思就是一个类尽量减少本人对其余对象的依赖,准则是低耦合,高内聚,只有使各个模块之间的耦合尽量的低,能力进步代码的复用率。
  • 长处:低耦合,高内聚。

繁多职责准则

  • 准则思维:一个办法只负责一件事件。
  • 形容:繁多职责准则很简略,一个办法 一个类只负责一个职责,各个职责的程序改变,不影响其它程序。 这是常识,简直所有程序员都会遵循这个准则。
  • 长处:升高类和类的耦合,进步可读性,减少可维护性和可拓展性,升高可变性的危险。

单例模式

什么是单例

保障一个类只有一个实例,并且提供一个拜访该全局拜访点

那些中央用到了单例模式

  1. 网站的计数器,个别也是采纳单例模式实现的,否则难以同步
  2. 应用程序的日志利用,个别也都是单例模式实现,只有一个实例去操作才好,否则内容不好最佳显示。
  3. 多线程的线程池的设计个别也是采纳单例模式,因为线程池要不便对池中的线程进行管制。
  4. Windows的工作管理器就是厂房典型的单例模式,他不能关上两个
  5. Windows的回收站也是经典的单例利用。在整个零碎运行过程中,回收站只能保护一个实例。

单例模式的优缺点

长处

  1. 在单例模式中,流动的单例只有一个实例,对单例类的所有实例化失去的都是雷同的一个实例。这样就避免其余对象对本人的实例化,确保所有的对象都拜访一个实例。
  2. 单例模式具备肯定的伸缩性,类本人来管制实例化过程,类就在扭转实例化过程上有相应的伸缩性。
  3. 提供了对惟一实例的受控拜访。
  4. 因为在零碎内存中只存在一个对象,因而能够节约系统资源,当须要频繁创立和销毁的对象时单例模式无疑能够提供零碎的性能。
  5. 容许可变数目标实例。
  6. 防止对共享资源的多重占用。

毛病

  1. 不适用于变动的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的谬误,不能保留彼此的状态。
  2. 因为单例模式中没有形象层,因而单例的扩大有很大的艰难。
  3. 单例类的职责过重,在肯定程序上违反了“繁多职责准则”。
  4. 滥用单例将带来一些负面问题,如为了节俭资源将数据库连接池对象设计为单例类,可能会导致共享连接池对象的程序过多而呈现连接池溢出;如果实例化的对象长时间不被利用,零碎会认为是垃圾而被回收,这将导致对象状态的失落。

单例模式应用注意事项

  1. 应用时不能用反射模式创立单例,否则会实例一个新的对象。
  2. 应用懒单例模式时留神线程平安问题。
  3. 饿单例模式和懒单例模式构造方法都是公有的,因而是不能被继承的,有些单例模式能够被继承(如注销式模式)

单例避免反射破绽攻打

private static boolean flag = false;private Singleton() {    if (flag == flase) {        flag = !flag;    } eLse {        thrown new RuntimeException("单例模式被进犯!");    }}

如何抉择单例创立形式

如果不须要提早加载单例,能够应用枚举或者饿汉式,相对来说枚举性好于饿汉式。如果须要提早加载,能够应用动态外部类或者懒汉式,相对来说动态外部类好于懒汉式。

单例创立形式

  1. 饿汉式:类初始化时,会立刻加载该对象,线程天生平安,调用效率高。
  2. 懒汉式:类初始化时,不会初始化该对象,真正须要应用的时候才会创立该对象,具备懒加载性能。
  3. 动态外部形式:联合了懒汉式和饿汉式格子的长处,真正须要对象的时候才会加载,加载相似线程平安的。
  4. 枚举单例:应用枚举实现单例模式

    • 长处:实现简略、调用效率高,枚举自身就是单例,因为JVM从根本上提供保障!防止通过反射和反序列化的破绽
    • 毛病:没有提早加载
  5. 双重检测锁形式:因为JVM实质重排序的起因,可能会初始化屡次,不举荐应用

饿汉式

类初始化时,会立刻加载该对象,线程天生平安,调用效率高。

public class Demo1 {    private static Demo1 demo1 = new Demo1();    private Demo1() {        System.out.println("公有Demo1结构参数初始化");    }    public static Demo1 getInstance() {        return demo1;    }    public static void main(String[] args) {        Demo1 s1 = Demo1.getInstance();        Demo1 s2 = Demo1.getInstance();        System.out.println(s1 == s2);    }}

懒汉式

类初始化时,不会初始化该对象,真正须要应用的时候才会创立该对象,具备懒加载性能。

public class Demo2 {    private static Demo2 demo2;    private Demo2() {        System.out.println("公有Demo2结构参数初始化");    }    public synchronized static Demo2 getInstance () {        if (demo2 == null) {            demo2 = new Demo2();        }        return demo2;    }    public static void main(String[] args) {        Demo2 s1 = Demo2.getInstance();        Demo2 s2 = Demo2.getInstance();        System.out.println(s1 == s2);    }}

动态外部类

动态外部类形式:联合了懒汉式和饿汉式格子的长处,真正须要对象的时候才会加载,加载类是线程平安的。

public class Demo3 {    private Demo3() {        System.out.println("Demo的公有结构参数办法");    }    public static class SingletonClassInstance{        private static final Demo3 DEMO_3 = new Demo3();    }    public static Demo3 getInstance() {        return SingletonClassInstance.DEMO_3;    }    public static void main(String[] args) {        Demo3 s1 = Demo3.getInstance();        Demo3 s2 = Demo3.getInstance();        System.out.println(s1 == s2);    }}

枚举单例式

应用枚举实现单例模式
长处:实现简略,调用效率高,枚举自身就是单例,由JVM从根本上提供保障!防止通过反射和反序列化的破绽
毛病:没有提早加载

工厂模式

什么是工厂模式

它提供了一种创建对象的最佳形式。在工厂模式中,咱们创建对象时不会对客户端裸露创立逻辑,并且是通过应用一个独特的接口来指向新创建的对象。实现了创建者和调用者拆散,工厂模式分为简略工厂、工厂办法、形象工程模式

工厂模式益处

  1. 工厂模式时咱们最罕用的实例化对象模式了,是用工厂办法代替new操作的一种模式。
  2. 利用工厂模式能够升高程序的耦合性,为前期的保护批改提供了很大的便当。
  3. 将抉择实现类、创建对象对立治理和管制。从而将调用者跟我妈的实现类解耦。

Spring开发中的工厂设计模式

  1. Spring IOC

    • 看过Spring源码就晓得,在SpringIOC容器创立bean的过程是应用了工厂设计模式。
    • Spring中无论是通过xml配置还是通过配置类还是通过注解进行创立bean,大部分都是通过简略工厂来进行创立的。
    • 当容器拿到了beanName和class类型后,动静的通过反射创立具体的某个对象,最初将创立的指向放到map中。

为什么Spring IOC 要应用工厂设计模式创立Bean呢?

  1. 在理论开发中,如果咱们A对象调用B,B调用C,C调用D的话咱们程序的耦合性就会变高。
  2. 在很久以前的三层架构编程时,都是管制层调用业务层,业务层调用数据拜访层时,都是间接new对象,耦合性大大晋升,代码反复量很高,对象满天飞。
  3. 为了防止这种状况,Spring应用工厂模式编程,写一个工厂,由工厂创立Bean,当前咱们如果要对象就间接管工厂要就能够了,剩下的事件不归咱们管了.Spring IOC容器的工厂中有个动态的Map汇合,是为了让工厂合乎单例设计模式,即每个对象只生产一次,生产出对象后就存入到Map汇合中,保障了实例不会反复影响程序效率。

工厂模式分类

  1. 简略工厂:用来生产同一等级构造中的任意产品
  2. 工厂办法:用来生产同一等级构造中的固定产品
  3. 形象工厂:用来生产不同产品组族的全副产品。

简略工厂模式

什么是简略工厂模式

简略工厂模式相等于是一个工厂中有各种产品,创立在一个类中,客户无需晓得具体产品的名称,只须要晓得产品类说对应失去参数即可。然而工厂的职责过重,而且当类型过多时不利于零碎的扩大保护。

代码演示:

  1. 创立工厂

    public interface Car {public void run();}
  2. 创立工厂的产品(如果为宝马)

    public class Bmw implements Car {@Overridepublic void run() {    System.out.println("我是宝马汽车......");    }}
  3. 创立工厂中的另外一种产品(如果为奥迪)

    public class AoDi implements Car{@Overridepublic void run() {    System.out.println("我是奥迪汽车......");    }}
  4. 创立外围工厂类,有他决定具体调用哪个产品

    public class CarFactory {public static Car createCar(String name) {    if ("".equals(name)) {        return null;    }    if (name.equals("奥迪")) {        return new AoDi();    }    if (name.equals("宝马")) {        return new Bmw();    }    return null;    }}
  5. 演示创立工厂的具体实例

    public class Client01 {public static void main(String[] args) {    Car aoDi = CarFactory.createCar("奥迪");    Car bmw = CarFactory.createCar("宝马");    aoDi.run();    bmw.run();;    }}

    单工厂的长处/毛病:
    长处:简略工厂模式可能依据外界给定的信息,决定到底应该创立哪个具体类的对象。明确辨别了各自的职责和势力,有利于整个软件体系结构的优化。
    毛病:很显著工厂类集中了所有实例的创立逻辑,容易违反高汇集的责任分配原则。

工厂办法模式

什么是工厂办法模式

工厂办法模式,又称为多态性工厂模式。在工厂办法模式中,外围的工厂类不在负责所有的产品的创立,而是将具体创立的工作交给子类去做。该外围类成为一个形象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类该当被实例化的这种细节。

代码演示:

  1. 创立工厂:

    public interface Car {public void run();}
  2. 创立工厂办法调用接口(所有的产品须要new进去必须继承他来实现办法)

    public interface CarFactory {Car createCar();}
  3. 创立工厂的第一种产品(假如为奥迪)

    public class AoDi implements Car{@Overridepublic void run() {    System.out.println("我是奥迪汽车......");    }}
  4. 创立工厂中的另外一个产品(假如为宝马)

    public class Bmw implements Car{@Overridepublic void run() {    System.out.println("我是宝马汽车......");    }}
  5. 创立工厂办法调用接口的实例(奥迪)

    public class AoDiFactory implements CarFactory{@Overridepublic Car createCar() {    return new AoDi();    }}
  6. 创立工厂办法调用接口的实例(宝马)

    public class BmwFactory implements CarFactory{@Overridepublic Car createCar() {    return new Bmw();    }}
  7. 演示创立工厂的具体实例

    public class Client {public static void main(String[] args) {    Car aodi = new AoDiFactory().createCar();    Car bmw = new BmwFactory().createCar();    aodi.run();    bmw.run();    }}

形象工厂模式

什么是形象工厂模式

形象工厂简略地说是工厂的工厂,形象工厂能够创立具体工厂,由具体工厂来产品具体产品。

代码演示:

  1. 创立第一个子工厂,及实现类

    public interface Car {void run();}class CarA implements Car {    @Override    public void run() {        System.out.println("宝马");    }}class CarB implements Car {    @Override    public void run() {        System.out.println("摩拜");    }}
  2. 创立第二个子工厂,及实现类

    public interface Engine {void run();}class EngineA implements Engine {    @Override    public void run() {        System.out.println("转的很快!");    }}class EngineB implements Engine {    @Override    public void run() {        System.out.println("转的慢!");    }}
  3. 创立一个总工厂,及实现类(由总工厂的实现类决定调用那个工厂的那个实例)

    public interface TotalFactory {// 创立汽车Car createChair();// 创立发动机Engine createEngine();}class TotalFactoryReally implements TotalFactory {    public Engine createEngine() {        return new EngineA();    }    public Car createChair() {        return new CarA();    }}
  4. 运行测试

    public class Client {public static void main(String[] args) {    TotalFactory totalFactory = new TotalFactoryReally();    Car car = totalFactory.createChair();    car.run();    TotalFactory factoryReally = new TotalFactoryReally();    Engine engine = factoryReally.createEngine();    engine.run();    }}

代理模式

什么是代理模式

  1. 通过代理管制对象的拜访,能够在这个对象调用办法之前、调用办法之后去解决/增加新的性能。(也就是AOP的微实现)
  2. 代理在原有代码乃至原业务流程都不批改的状况下,间接在业务流程中切入行新代码,减少新性能,这也和Spring(面向切面编程)很类似。

代理模式利用场景

Spring AOP、日志打印、异样解决、事务管制、权限管制等等

代理的分类

  1. 动态代理(动态定义代理类)
  2. 动静代理(动静生成代理类,也称为JDK自带动静代理)
  3. Cglib、javaassist(字节码操作库)

三种代理的区别

  1. 动态代理:简略代理模式,是动静代理的实践根底。常见应用在代理模式。
  2. JDK动静代理:应用反射实现代理。须要有顶层接口能力应用,常见是myabtis的mapper文件是代理。
  3. cglib动静代理:也是应用反射实现代理,能够间接代理类(jdk动静代理不行),应用字节码技术,不能对final类进行继承。(须要导入jar包)

用代码演示三种代理

动态代理

什么是动态代理

由程序员创立或工具生成代理类的源码,再编译代理类。所谓动态也就是程序运行前就曾经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。

我有一段这样的代码:(如何能在不批改UserDao接口类的状况下开事务和敞开事务呢)

public class UserDao {    public void save() {        System.out.println("保留数据办法");    }}
public class Test {    public static void main(String[] args) {        UserDao userDao = new UserDao();        userDao.save();    }}

批改代码,增加代理类

public class UserDaoProxy extends UserDao{    private UserDao userDao;    public UserDaoProxy(UserDao userDao) {        this.userDao = userDao;    }    public void save() {        System.out.println("开启事务...");        userDao.save();        System.out.println("敞开事务...");    }}
public class ProxyTest {    public static void main(String[] args) {        UserDao userDao = new UserDao();        UserDaoProxy userDaoProxy = new UserDaoProxy(userDao);        userDaoProxy.save();    }}
  • 长处:能够面相理论对象或者是接口的形式实现代理
  • 毛病:每个须要代理的对象都须要本人反复编写代理,很不难受。

动静代理

什么是动静代理

  • 动静代理也叫做,JDK代理、接口代理。
  • 动静代理的对象,是利用JDK的API,动静的在内存中构建代理对象(是依据被代理的接口来动静生成代理类的class文件,并加载运行的过程),这就叫动静代理。
    源代码:

    public interface UserDao {  void save();}
    public class UserDaoImpl implements UserDao{  @Override  public void save() {      System.out.println("保留数据办法");  }}

    上面是代理类,可重复使用,不像动态代理那样要本人反复编写代理。

    /** * 每次生成动静代理类对象,实现了InvocationHandler接口的调用处理器对象 */public class InvocationHandlerImpl implements InvocationHandler {  /**   * 这位业务实现类对象,用来调用具体的业务办法   */  private Object target;  /**   * 通过构造函数传入指标对象   */  public InvocationHandlerImpl(Object target) {     this.target = target;  }  /**   * 动静代理理论运行的代理办法   */  @Override  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {      System.out.println("调用开始解决");      // 上面invoke()办法是以反射的形式来创建对象,第一个参数是要创立的对象,第二个是形成办法的参数,由第二个参数决定创立指向应用哪个构造方法      Object result = method.invoke(target, args);      System.out.println("调用完结解决");      return result;  }}
    public class Test {  public static void main(String[] args) {      // 被代理对象      UserDao userDao = new UserDaoImpl();      InvocationHandlerImpl invocationHandler = new InvocationHandlerImpl(userDao);      // 类加载器      ClassLoader loader = userDao.getClass().getClassLoader();      Class<?>[] interfaces = userDao.getClass().getInterfaces();      // 次要装载器、一组接口及调用解决动静代理实例      UserDao newProxyInstance = (UserDao) Proxy.newProxyInstance(loader, interfaces, invocationHandler);      newProxyInstance.save();  }}
  • 毛病:必须是面向接口,指标业务类必须实现接口。
  • 长处:不必关怀代理类,只须要在运行阶段才指定代码哪一个对象。

CGLIB动静代理

CGLI动静代理原理

利用asm开源包,对代理对象类的class文件加载进来,通过批改其字节码生成之类来解决。

什么是CGLIB动静代理

CGLIB动静代理和jdk代理一样,应用反射实现代理,不同的是他能够间接代理类(jdk代理不行,他必须指标业务类必须实现接口),CGLIB动静代理底层应用字节码技术,CGLIB动静代理通能对final类进行继承。(CGLIB动静代理须要导入jar包)

代码演示:

源代码:

public interface UserDao {    void save();}
public class UserDaoImpl implements UserDao{    @Override    public void save() {        System.out.println("保留数据的办法");    }}

退出代理类:

import org.springframework.cglib.proxy.Enhancer;import org.springframework.cglib.proxy.MethodInterceptor;import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/** * 代理次要类 */public class CglibProxy implements MethodInterceptor {    private Object targetObject;    /**     * 这里的指标类型为Object,则能够承受任意一种参数作为被代理类,实现了动静代理     */    public Object getInstance(Object target) {        // 设置须要创立子类的类        this.targetObject = target;        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(target.getClass());        enhancer.setCallback(this);        return enhancer.create();    }    /**     * 代理的理论办法     */    @Override    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {        System.out.println("开启事务");        Object result = methodProxy.invoke(targetObject, objects);        System.out.println("敞开事务");        return result;    }}
public class Test {    public static void main(String[] args) {        CglibProxy cglibProxy = new CglibProxy();        UserDao userDao = (UserDao) cglibProxy.getInstance(new UserDaoImpl());        userDao.save();    }}

建造者模式

什么是建造者模式

  1. 建造者模式:是将一个简单的对象的构建与它的示意拆散,使得同样的构建过程能够创立不同的形式进行创立。
  2. 工厂类模式提供的是创立单个类的产品,而建造者模式这是将各种产品集中起来进行治理,用来具备不同的属性的产品。

建造者模式通常包含上面几个角色

  1. Builder:给出一个形象接口,以标准产品对象的各个组成成分的建造。这个接口规定要实现简单对象的哪些局部的创立,并不波及具体的对象部件的创立。
  2. ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化简单对象的各局部的创立。在建造过程实现后,提供产品的实例。
  3. Director:调用具体建造者来创立简单对象的各个局部,在指导者中不波及具体产品的信息,只负责保障对象各局部残缺创立或按某种程序创立。
  4. Product:要创立的简单对象

建造者模式的应用场景

应用场景

  1. 须要生成的对象具备简单的内部结构。
  2. 须要生成的对象外部属性自身相互依赖。
  • 与工厂模式的区别是:建造者模式更加关注与整机拆卸的程序。
  • Java中的StringBuilder就是建造者模式创立的,他吧一个单个只剩的char数组组合起来。
  • Spring不是建造者模式,他提供的操作应该是对于字符串自身的一些操作,而不是创立或扭转一个字符串。

代码演示:

  1. 建设一个配备对象Arms

    import lombok.Data;/** * 配备类 */@Datapublic class Arms {    // 头盔    private String helmet;    // 铠甲    private String armor;    // 武器    private String weapon;}
  2. 创立Builder接口(给出一个形象接口,以标准产品对象的各个组成成分的建造,这个接口只是标准)

    public interface PersonBuilder {void builderHelmetMurder();void builderArmorMurder();void builderWeaponMurder();void builderHelmetYanLong();void builderArmorYanLong();void builderWeaponYanLong();// 组装Arms builderArms();}
  3. 创立Builder实现类(这个类次要实现简单对象创立的哪些局部须要什么属性)

    public class ArmsBuilder implements PersonBuilder{    private Arms arms;    public ArmsBuilder() {        arms = new Arms();    }    @Override    public void builderHelmetMurder() {        arms.setHelmet("夺命头盔");    }    @Override    public void builderArmorMurder() {        arms.setArmor("夺命盔甲");    }    @Override    public void builderWeaponMurder() {        arms.setWeapon("夺命宝刀");    }    @Override    public void builderHelmetYanLong() {        arms.setHelmet("炎龙头盔");    }    @Override    public void builderArmorYanLong() {        arms.setArmor("炎龙铠甲");    }    @Override    public void builderWeaponYanLong() {        arms.setWeapon("炎龙宝刀");    }    @Override    public Arms builderArms() {        return arms;    }}
  4. Director(调用具体建造者来创立简单对象的各个局部,在指导者中不波及具体产品的信息,只负责保障对象各局部残缺创立或按某种程序创立)

    public class PersonDirector {/** * 组装 */public Arms constructPerson(PersonBuilder pb) {    pb.builderHelmetYanLong();    pb.builderArmorMurder();    pb.builderWeaponMurder();    return pb.builderArms();}/** * 开始进行测试 */public static void main(String[] args) {    PersonDirector personDirector = new PersonDirector();    Arms arms = personDirector.constructPerson(new ArmsBuilder());    System.out.println(arms.getHelmet());    System.out.println(arms.getArmor());    System.out.println(arms.getWeapon());}

模板办法模式

什么是模板办法

模板办法模式:定义一个操作中的算法骨架(父类),而将一些步骤提早到子类中。模板办法是得子类能够不扭转一个算法的构造来重定义该算法的。

什么时候应用模板办法

实现一些操作时,整体步骤很固定,然而呢。就是其中一小部分须要扭转,这时候能够应用模板办法模式,将容易变的局部形象进去,供子类实现。

理论开发中利用场景哪里用到了模板办法

  1. 其实很多框架中都有用到了模板办法模式
  2. 例如:数据库拜访的封装、Junit单元测试、servlet中对于doGet/doPost办法的调用等等

现实生活中的模板办法

例如:去餐厅吃饭,餐厅给咱们提供了一个模板就是:看菜单、点菜、吃饭、付款、走人(这里“点菜和付款”是不确定的由子类来实现的,其余的则是一个模板)

代码演示:

  1. 先定义一个模板,把模板中的点菜和付款,让子类来实现。

    /** * 模板办法 */public abstract class RestaurantTemplate {    /**     * 看菜单     */    public void menu() {        System.out.println("看菜单");    }    /**     * 点菜业务     */    abstract void spotMenu();    /**     * 吃饭业务     */    public void havingDinner() {        System.out.println("吃饭");    }    /**     * 付款业务     */    abstract void payment();    /**     * 走人     */    public void GoR() {        System.out.println("走人");    }    /**     * 模板通用构造     */    public void process() {        menu();        spotMenu();        havingDinner();        payment();        GoR();    }}
  2. 具体的模板办法子类one

    public class RestaurantLobsterImpl extends RestaurantTemplate{    /**     * 点菜业务     */    @Override    void spotMenu() {        System.out.println("龙虾");    }    /**     * 付款业务     */    @Override    void payment() {        System.out.println("50块");    }}
  3. 具体的模板办法子类two

    public class RestaurantGinsengImpl extends RestaurantTemplate{    /**     * 点菜业务     */    @Override    void spotMenu() {        System.out.println("人参");    }    /**     * 付款业务     */    @Override    void payment() {        System.out.println("5块");    }}
  4. 客户端测试

    public class Client {    public static void main(String[] args) {        RestaurantLobsterImpl restaurantLobster = new RestaurantLobsterImpl();        restaurantLobster.process();    }}

外观模式

什么是外观模式

  1. 外观模式:也叫门面模式,暗藏零碎的复杂性,并向客户端提供了一个客户端能够拜访零碎的接口。
  2. 它向现有的零碎增加一个接口,用这一个接口来暗藏理论的零碎的复杂性。
  3. 应用外观模式,他内部看起来就是一个接口,其实他的外部有很多简单的接口曾经被实现。

代码演示:

用户注册完之后,须要调用阿里短信接口、邮件接口、微信推送接口。

  1. 创立阿里短信接口

    /** * 阿里短信音讯 */public interface AliSmsService {    void sendSms();}
    public class AliSmsServiceImpl implements AliSmsService{    @Override    public void sendSms() {        System.out.println("阿里短信音讯");    }}
  2. 创立邮件接口

    /** * 发送邮件音讯 */public interface EamilSmsService {    void sendSms();}
    public class EamilSmsServiceImpl implements EamilSmsService{    @Override    public void sendSms() {        System.out.println("发送邮件音讯");    }}
  3. 创立微信推送接口

    /** * 微信音讯推送 */public interface WeixinSmsService {    void sendSms();}
    public class WeiXinSmsServiceImpl implements WeixinSmsService{    @Override    public void sendSms() {        System.out.println("发送微信音讯推送");    }}
  4. 创立门面(门面看起来很简略,简单的货色以及被门面给封装好了)

    public class Computer {    AliSmsService aliSmsService;    EamilSmsService eamilSmsService;    WeixinSmsService weixinSmsService;    public Computer() {        aliSmsService = new AliSmsServiceImpl();        eamilSmsService = new EamilSmsServiceImpl();        weixinSmsService = new WeiXinSmsServiceImpl();    }    /**     * 只须要调用它     */    public void sendMsg() {        aliSmsService.sendSms();        eamilSmsService.sendSms();        weixinSmsService.sendSms();    }}
  5. 进行测试

    public class Client {    public static void main(String[] args) {        new Computer().sendMsg();    }}

原型模式

什么原型模式

  1. 原型设计模式简略来说就是克隆
  2. 原型表明了有一个样板实例,这个原型是可定制的。原型模型多用于创立简单的或者结构耗时的实例,因为这种状况下,复制一个曾经存在的实例可使程序运行更高效。

原型模式的利用场景

  1. 类初始化须要消化十分多的资源,这个资源包含数据、硬件资源等。这时咱们就能够通过原型拷贝防止这些耗费。
  2. 通过new产生的一个对象须要十分繁琐的数据筹备或者权限,这时能够应用原型模式。
  3. 一个对象须要提供给其余对象拜访,而且各个调用者可能都须要批改其值时,能够思考应用原型模式拷贝多个对象供调用者应用,即保护性拷贝。

原型模式的应用形式

  1. 实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时告诉虚拟机能够平安地在实现了此接口的类上应用clone办法。在java虚拟机中,只有实现了这个接口的类才能够被拷贝,否则在运行时会抛出CloneNotSupportedException异样。
  2. 重写Object类中的clone办法。Java中,所有类的父类都是Object类,Object类中有一个clone办法,作用是返回对象的一个拷贝,然而其作用域protected类型的,个别的类无奈调用,因而Prototype类须要将clone办法的作用域批改为public类型。