目录

一、简单工厂模式(Factory Method)

二、工厂方法模式

三、抽象工厂模式(Abstract Factory)

3.1 三个工厂模式区别:

四、单例模式(Singleton)

1、饿汉式

2、懒汉式

3、嵌套类最经典,以后大家就用它吧

五、代理模式(Proxy)

1、静态代理

2、动态代理

3、Cglib

动态代理对比:

六、装饰者模式(Decorator)

七、策略模式(简单&常用)(Strategy)

7.1 代理模式、装饰器模式、策略模式的区别

八、观察者模式(面试时手写)(Observer)

九、模板方法模式(Template Method)

十、适配器模式(Adapter)

todo: 待补充

十一、建造者模式(Builder)


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

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

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

本文选取部分常用的设计模式:

一、简单工厂模式(Factory Method)

一些容易变化的地方,考虑用一个单独的类来做这个实例化的过程,这就是工厂。

先来看看它的组成:

1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由 一个具体类实现。

2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽 象类来实现。

3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现

//抽象产品角色
public interface Car {public void drive();
}
//具体产品角色
public class Benz implements Car {@Overridepublic void drive() {System.out.println("生产 Benz");}
}
//具体产品角色
public class Bmw implements Car {@Overridepublic void drive() {System.out.println("生产 Bmw");}
}
//工厂类角色
public class Driver {//注意:返回类型为抽象产品角色public static Car driveCar(String s)throws Exception{//判断逻辑,返回具体的产品角色给Clientif(s.equalsIgnoreCase("Benz")) {return new Benz();}else if(s.equalsIgnoreCase("Bmw")) {return new Bmw();}else {throw new Exception();}}
}
/*** 简单工厂模式:*         包含的接口和类为:Car、Benz、Bmw、Driver* @author Mona**/public class MagNate {public static void main(String[] args) {try {//生产奔驰Car car = Driver.driveCar("Benz");car.drive();} catch (Exception e) {}}
}

二、工厂方法模式

工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂实例来创建不同的产品实例。 在同一等级结构中,支持增加任意产品。

在上面代码的基础之上,再增加下面的代码:生产汽车的工厂接口
public interface CarFactory {Car produce();
}
public class BenchiFactory implements CarFactory {@Overridepublic Car produce() {return new Benchi();}
}
public class BwmFactory implements CarFactory {@Overridepublic Car produce() {return new Bwm();}
}
public static void main(String[] args) {// 先创建 汽车工厂CarFactory benchiFactory = new BenchiFactory();benchiFactory.produce().drive();// 这个模式对于同一级别的产品,可扩展性高// 可以扩展不同品牌的汽车,此时不需要修改代码,只需要增加代码即可// 创建一个新的品牌汽车  宝马// new 另外的工厂  :  new BwmFactory();
}

三、抽象工厂模式(Abstract Factory)

抽象工厂模式的用意为:

给客户端提供一个接口,可以创建多个产品族中的产品对象,而且使用抽象工厂模式还要满足以下条件:

1) 系统中有多个产品族,而系统一次只可能消费其中一族产品。

2) 同属于同一个产品族的产品一起使用

迷你汽车接口
public interface MiniCar {void showInfo();
}
SUV汽车接口
public interface SUVCar {void showInfo();
}
public class AudiMiniCar implements MiniCar {@Overridepublic void showInfo() {System.out.println("这是奥迪迷你汽车 ");}
}public class BMWMiniCar implements  MiniCar {@Overridepublic void showInfo() {System.out.println("这是宝马Cooper迷你汽车");}
}
public class AudiSUVCar implements  SUVCar {@Overridepublic void showInfo() {System.out.println("这是一辆 奥迪SUV汽车");}
}public class BMWSUVCar implements  SUVCar {@Overridepublic void showInfo() {System.out.println("这宝马的SUV系列");}
}
public interface CarFactorys {// 生成不同型号的汽车 ,两条产品线MiniCar produceMiniCar();SUVCar produceSUVCar();
}public class AudiCarFactory implements CarFactorys {@Overridepublic MiniCar produceMiniCar() {return new AudiMiniCar();}@Overridepublic SUVCar produceSUVCar() {return new AudiSUVCar();}
}public class BMWCarFactory implements CarFactorys {@Overridepublic MiniCar produceMiniCar() {return new BMWMiniCar();}@Overridepublic SUVCar produceSUVCar() {return new BMWSUVCar();}
}
public static void main(String[] args) {BMWCarFactory bmwCarFactory = new BMWCarFactory();MiniCar miniCar = bmwCarFactory.produceMiniCar();miniCar.showInfo();
}

3.1 三个工厂模式区别:

1、对于简单工厂,用于生产同一结构中的任意产品,对于新增产品不适用。

2、对于工厂方法,在简单工厂的基础上,生产同一等级结构中笃定产品,可以支持新增产品。

3、抽象工厂,用于生产不同种类(品牌)的相同类型(迷你,SUV),对于新增品牌可以,不支持新增类型

四、单例模式(Singleton)

一步步分析:

1、属性

2、方法------------不行 每一次执行都会产生一个过程 保证不了唯一性

3、构造方法------不行 私有 本身就是这个构造过程

4、块--------------不行 没有返回值 创建了对象也无法给别人使用

单例模式的实现:

1、私有的构造方法

2、私有的静态的当前类对象作为属性

3、公有的静态的方法返回当前类对象

单例模式又叫做单态模式或者单件模式。在 GOF 书中给出的定义为:保证一个类仅有 一个实例,并提供一个访问它的全局访问点。单例模式中的“单例”通常用来代表那些本质上 具有唯一性的系统组件(或者叫做资源)。比如文件系统、资源管理器等等。

单例模式的目的就是要控制特定的类只产生一个对象,当然也允许在一定情况下灵活的 改变对象的个数那么怎么来实现单例模式呢?一个类的对象的产生是由类构造函数来完成 的,如果想限制对象的产生,一个办法就是将构造函数变为私有的(至少是受保护的),使 得外面的类不能通过引用来产生对象;同时为了保证类的可用性,就必须提供一个自己的对 象以及访问这个对象的静态方法。

现在对单例模式有了大概的了解了吧,其实单例模式在实现上是非常简单的——只有一 个角色,而客户则通过调用类方法来得到类的对象。

放上一个类图吧,这样更直观一些:

1、饿汉式

/*** 单例模式------ 1、饿汉式  ==   线程安全* *        单例:不是无例  ---在本类中的某个成员位置上创建唯一的一个对象* * 在类被加载的时候实例化,这样多次加载会照成多次实例* * @author Mona**/
public class EHanShiSingleton {//在自己内部定义自己一个实例 //注意这是 private 只供内部调用 private static EHanShiSingleton instance = new EHanShiSingleton();//直接new,立即加载//如上面所述,将构造函数设置为私有private EHanShiSingleton() {}//静态工厂方法,提供了一个供外部访问得到对象的静态方法public static EHanShiSingleton geInstance() {return instance;}
}

2、懒汉式

/*** * 单例模式-----2、懒汉式* *     防止多线程环 境中产生多个实例*  使用了 同步处理,在反应速度上要比第一种慢一些。  * * @author Mona**/
public class LazySingleton {// 和饿汉模式相比,这边不需要先实例化出来,注意这里的 volatile,它是必须的private static volatile LazySingleton instance = null;//设置为私有的构造函数private LazySingleton() {}/*** 静态工厂方法-----(提供一个获取单个对象的方法给用户)* 返回值  将对象返回出去* * @return*/public static LazySingleton getInstance() {//将类对自己的实例化延迟到第一次被引用的时候。if(instance == null) {// 加锁synchronized (LazySingleton.class) {这一次判断也是必须的,不然会有并发问题if(instance == null) {instance = new LazySingleton();}}}return instance;//引用类型}
}       

以上两种实现方式均失去了多态性,不允许被继承。

将构造函数设置为受保护的,这样允许被继承产生子类。

双重检查,指的是两次检查 instance 是否为 null。

volatile 在这里是需要的,为了保证线程可见性,可以重点查下volatile的作用。

很多人不知道怎么写,直接就在 getInstance() 方法签名上加上 synchronized,这就不多说了,性能太差。

3、嵌套类最经典,以后大家就用它吧

public class Singleton3 {private Singleton3() {}// 主要是使用了 嵌套类可以访问外部类的静态属性和静态方法 的特性private static class Holder {private static Singleton3 instance = new Singleton3();}public static Singleton3 getInstance() {return Holder.instance;}
}

注意,很多人都会把这个嵌套类说成是静态内部类,严格地说,内部类和嵌套类是不一样的,它们能访问的外部类权限也是不一样的。

由于在 java 中子类的构造函数的范围不能比父类的小,所以可能存在不守规则的客户 程序使用其构造函数来产生实例,造成单例模式失效。

//总结一个完美的单例模式
public class Singleton {  /* 私有构造方法,防止被实例化 */  private Singleton() {  }  /* 此处使用一个内部类来维护单例 */  private static class SingletonFactory {  private static Singleton instance = new Singleton();  }  /* 获取实例 */  public static Singleton getInstance() {  return SingletonFactory.instance;  }  /* 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 */  public Object readResolve() {  return getInstance();  }
}

其实说它完美,也不一定,如果在构造函数中抛出异常,实例将永远得不到创建,也会出错。

五、代理模式(Proxy)

代理模式是最常使用的模式之一

既然说是代理,那就要对客户端隐藏真实实现,由代理来负责客户端的所有请求。当然,代理只是个代理,它不会完成实际的业务逻辑,而是一层皮而已,但是对于客户端来说,它必须表现得就是客户端需要的真实实现。

1、静态代理

静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类.

调用的时候通过调用代理对象的方法来调用目标对象.

需要注意的是,代理对象与目标对象要实现相同的接口,然后通过调用相同的方法来调用目标对象的方法.

/*** 接口* * @author Mona**/
public interface UserDao {void save();
}
/*** 接口实现* 目标对象* * @author Mona**/
public class UserDaoImpl implements UserDao{@Overridepublic void save() {System.out.println("-------已保存数据--------");}
}
/*** 代理对象,静态代理* * @author Mona**/
public class UserDaoProxy implements UserDao {//接收保存目标对象private UserDaoImpl target;public UserDaoProxy(UserDaoImpl target) {this.target = target;}@Overridepublic void save() {System.out.println("开始事务...");target.save();//执行目标对象的方法System.out.println("提交事务...");}
}
/*** 测试类* * @author Mona**/
public class ProxyAppTest {public static void main(String[] args) {//目标对象UserDaoImpl target = new UserDaoImpl();//代理对象,把目标对象传给代理对象,建立代理关系UserDaoProxy proxy = new UserDaoProxy(target);proxy.save();//执行的是代理的方法}
}

静态代理总结:

1.可以做到在不修改目标对象的功能前提下,对目标功能扩展.

2.缺点:

因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.

如何解决静态代理中的缺点呢?

答案是可以使用动态代理方式

代理模式的应用场景:

如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:

1、修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则。

2、就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。

使用代理模式,可以将功能划分的更加清晰,有助于后期维护!

2、动态代理

动态代理有以下特点:

1.代理对象,不需要实现接口

2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)

3.动态代理也叫做:JDK代理,接口代理

JDK中生成代理对象的API

代理类所在包:java.lang.reflect.Proxy

JDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个参数,完整的写法是:

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )

直接使用静态代理中的接口及接口实现类,目标对象UserDaoImpl也没有修改

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** 2、创建动态代理对象(JDK代理)* 动态代理不需要实现接口,但是需要指定接口类型* * @author Mona**/
public class ProxyFactory {//维护一个目标对象private Object target;public ProxyFactory(Object target) {this.target = target;}//给定目标对象生成代理对象public Object getProxyInstance() {return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("开启事务~");// 执行目标对象方法Object returnValue = method.invoke(target, args);System.out.println("提交事务~");return null;}});}
}
/*** 动态代理---测试类* * @author Mona**/
public class ProxyTestDynamic {public static void main(String[] args) {//目标对象UserDao target = new UserDaoImpl();System.out.println(target.getClass());//给目标对象,创建代理对象UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance();//内存中动态生成的代理对象System.out.println(proxy.getClass());//执行方法  【代理】proxy.save();}
}

输出结果:


开启事务~
-------已保存数据--------
提交事务~

总结:

代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理

3、Cglib

  • JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。
    如果想代理没有实现接口的类,就可以使用CGLIB实现。
  • CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。
    它广泛的被许多AOP的框架使用,例如Spring AOP,为他们提供方法的拦截
/*** 目标对象** @author mona* @date 2021/11/18 15:09*/
public class CglibDao {public void save() {System.out.println("保存数据");}
}
/*** 代理对象** @author mona* @date 2021/11/18 15:09*/
public class CglibProxyFactory implements MethodInterceptor {private Object target;public CglibProxyFactory(Object object) {this.target = object;}public Object getProxyInstance() {// 工具类Enhancer enhancer = new Enhancer();// 设置父类enhancer.setSuperclass(target.getClass());enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("开启事务。。。sss");method.invoke(target, objects);System.out.println("关闭事务。。。eeee");return null;}
}
public class CglibTest {@Testpublic void cjlibTest() {// 目标对象CglibDao cjlibDao = new CglibDao();System.out.println(cjlibDao.getClass());// 代理对象CglibDao proxy = (CglibDao) new CglibProxyFactory(cjlibDao).getProxyInstance();System.out.println(proxy.getClass());proxy.save();}
}

结果:

class com.juc.demo.review.proxypag.CglibDao
class com.juc.demo.review.proxypag.CglibDao$$EnhancerByCGLIB$$f86aa22e
开启事务。。。sss
保存数据
关闭事务。。。eeee

动态代理对比:

  1. jdk动态代理必须实现InvocationHandler接口,通过反射代理方法,比较消耗系统性能,但可以减少代理类的数量,使用更灵活。
  2. cglib代理无需实现接口,通过生成类字节码实现代理,比反射稍快,不存在性能问题,但cglib会继承目标对象,需要重写方法,所以目标对象不能为final类。

六、装饰者模式(Decorator)

装饰器模式的应用场景:

1、需要扩展一个类的功能。

2、动态的为一个对象增加功能,而且还能动态撤销。(继承不能做到这一点,继承的功能是静态的,不能动态增删。)

缺点:产生过多相似的对象,不易排错!

public interface Human {void run();
}
public class Man implements Human{@Overridepublic void run() {System.out.println("人可以跑");}
}
// 装饰的抽象类
public class AbstractDecorator implements Human {// 持有被装饰类的引用private Human human;public AbstractDecorator(Human human) {this.human = human;}// 调用被装饰类的方法@Overridepublic void run() {human.run();}
}
public class ManDecorate extends AbstractDecorator {public ManDecorate(Human human) {// 调用父类的构造方法super(human);}// 装饰类增加的功能private void fly() {System.out.println("现在人可以飞了");}@Overridepublic void run() {super.run();fly();}
}
//测试
public class DecorateClient {public static void main(String[] args) {Human human = new Man();ManDecorate manDecorate = new ManDecorate(human);manDecorate.run();}
}

装饰模式与代理模式的区别:

装饰模式:侧重给一个实现类动态添加功能,不会对实现类的方法进行过滤拦截

代理模式:侧重将一个实现类的功能,委托给代理类来处理,可以对实现类的方法进行过滤拦截

七、策略模式(简单&常用)(Strategy)

策略模式(Strategy)属于对象行为型设计模式,主要是定义一系列的算法,把这些算法一个个封装成拥有共同接口的单独的类,并且使它们之间可以互换。

它将算法的使用和算法本身分离,即将变化的具体算法封装了起来,降低了代码的耦合度,系统业务策略的更变仅需少量修改。

策略模式由三个角色组成:

1) 算法使用环境(Context)角色:算法被引用到这里和一些其它的与环境有关的操作一起来完成任务。

2) 抽象策略(Strategy)角色:规定了所有具体策略角色所需的接口。在 java 它通常由接口或者抽象类来实现。

3) 具体策略(Concrete Strategy)角色:实现了抽象策略角色定义的接口。 策略模式各个角色之间关系的类图表示:

/*** 策略接口* * @author Mona**/
public interface Strategy {void doWork();
}
/*** 具体策略角色1* * @author Mona**/
public class ConcreteStrategy1 implements Strategy{@Overridepublic void doWork() {System.out.println("具体策略1工作");}
}
/*** 具体策略角色2* * @author Mona**/
public class ConcreteStrategy2 implements Strategy{@Overridepublic void doWork() {System.out.println("具体策略2工作");}
}
/*** 使用策略的类---封装角色* * @author Mona**/
public class ContextStrategy {//抽象策略private Strategy mStrategy;public ContextStrategy(Strategy strate) {this.mStrategy = strate;}//封装后,策略方法public void onAnyWork() {mStrategy.doWork();}
}
/*** 策略模式测试* * @author Mona**/
public class StrategyTest {public static void main(String[] args) {Strategy mStrategy = new ConcreteStrategy1();// 声明上下文ContextStrategy context = new ContextStrategy(mStrategy);// 执行封装后的方法context.onAnyWork();context = new ContextStrategy(new ConcreteStrategy2());// 执行封装后的方法context.onAnyWork();}
}

优点:

1)良好的扩展性。增加一种策略,只要实现接口,写上具体逻辑就可以了。当旧策略不需要时,直接剔除就行。

2)良好的封装性。策略的入口封装在Context封装类中,客户端只要知道使用哪种策略就传哪种策略对象就可以了。

3)避免了像简单工厂模式这样的多重条件判断。

缺点:

1)客户端必须了解策略组的各个策略,并且决定使用哪一个策略,也就是各个策略需要暴露给客户端。

2)如果策略增多,策略类的数量就会增加。

7.1 代理模式、装饰器模式、策略模式的区别

八、观察者模式(面试时手写)(Observer)

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式对于我们来说,真是再简单不过了。无外乎两个操作,观察者订阅自己关心的主题和主题有数据变化后通知观察者们。

首先,需要定义主题,每个主题需要持有观察者列表的引用,用于在数据变更的时候通知各个观察者:

public class Subject {private List<Observer> observers = new ArrayList<Observer>();private int state;public int getState() {return state;}public void setState(int state) {this.state = state;// 数据已变更,通知观察者们notifyAllObservers();}public void attach(Observer observer){observers.add(observer);        }// 通知观察者们public void notifyAllObservers(){for (Observer observer : observers) {observer.update();}}
}

定义观察者接口:

public abstract class Observer {protected Subject subject;public abstract void update();
}

其实如果只有一个观察者类的话,接口都不用定义了,不过,通常场景下,既然用到了观察者模式,我们就是希望一个事件出来了,会有多个不同的类需要处理相应的信息。比如,订单修改成功事件,我们希望发短信的类得到通知、发邮件的类得到通知、处理物流信息的类得到通知等。

我们来定义具体的几个观察者类:

public class BinaryObserver extends Observer {// 在构造方法中进行订阅主题public BinaryObserver(Subject subject) {this.subject = subject;// 通常在构造方法中将 this 发布出去的操作一定要小心this.subject.attach(this);}// 该方法由主题类在数据变更的时候进行调用@Overridepublic void update() {String result = Integer.toBinaryString(subject.getState());System.out.println("订阅的数据发生变化,新的数据处理为二进制值为:" + result);}
}public class HexaObserver extends Observer {public HexaObserver(Subject subject) {this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {String result = Integer.toHexString(subject.getState()).toUpperCase();System.out.println("订阅的数据发生变化,新的数据处理为十六进制值为:" + result);}
}

客户端使用也非常简单:

public static void main(String[] args) {// 先定义一个主题Subject subject1 = new Subject();// 定义观察者new BinaryObserver(subject1);new HexaObserver(subject1);// 模拟数据变更,这个时候,观察者们的 update 方法将会被调用subject.setState(11);
}

output:

订阅的数据发生变化,新的数据处理为二进制值为:1011
订阅的数据发生变化,新的数据处理为十六进制值为:B

九、模板方法模式(Template Method)

一个抽象类中,有一个主方法,再定义1...n个方法,可以是抽象的,也可以是实际的方法,定义一个类,继承该抽象类,重写抽象方法,通过调用抽象类,实现对子类的调用。

1) 抽象类(Abstract Class):定义了一到多个的抽象方法,以供具体的子类来实现它们; 而且还要实现一个模板方法,来定义一个算法的骨架。

该模板方法不仅调用前面的抽象方法,也可以调用其他的操作,只要能完成自身的使命。

2) 具体类(Concrete Class):实现父类中的抽象方法以完成算法中与特定子类相关的步骤。

在含有继承结构的代码中,模板方法模式是非常常用的,这也是在开源代码中大量被使用的。

/*** 模板设计模式*     模板方法只负责定义第一步应该要做什么,第二步应该做什么,第三步应该做什么,至于怎么做,由子类来实现。* * @author Mona**/
public abstract class AbstractTemplate {//这是模板方法public void templateMethod() {init();apply();end();}protected void init() {System.out.println("init 抽象层已经实现,子类也可以选择覆盖");}//留给子类实现protected abstract void apply();  //apply() 是抽象方法,子类必须实现它protected void end() {}
}
/*** 模板方法的一个实现类* * @author Mona**/
public class ConcreteTemplate extends AbstractTemplate{@Overridepublic void apply() {System.out.println("子类实现抽象方法 apply");}@Overridepublic void end() {System.out.println("我们可以把 method3 当作钩子方法来使用,需要的时候覆盖就可以了");}
}
public class TemplateTest {public static void main(String[] args) {AbstractTemplate t = new ConcreteTemplate();//调用模板方法t.templateMethod();}
}/*** JAVA 通过父类对象new 子类对象,这个对象的声明的类型就是父类的类型,* 调用这个对象的方法也只能是父类型的方法,子类独有的方法是不能够被使用的。* * 例如 :*         List alist =new ArrayList<>();//只能用List中的方法*    ArrayList arrayList=new ArrayList<>();//可以用arraylsit独有的属性和方法 * * 面向接口编程的思想:*         之所以要用父类来new子类,而不是直接用子类 new 子类,*       是因为假如以后要重构代码,*       把ArrayList换成LinkedList  那么采用这种方式,*       只需要修改一行代码即可,若是直接new*         那么后面的所有用到的 ArrayList 的地方就都要改动* */

很简单,一看就懂,重要的是熟练使用。

适用情况 :

根据上面对定义的分析,以及例子的说明,可以看出模板方法适用于以下情况:

1) 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。

2) 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。其实这可以说是一种好的编码习惯了。

3) 控制子类扩展。模板方法只在特定点调用操作,这样就只允许在这些点进行扩展。

如果你不愿子类来修改你的模板方法定义的框架,你可以采用两种方式来做:一是在 API 中不体现出你的模板方 法;或者将你的模板方法置为 final 就可以了。

可以看出,使用模板方法模式可以将代码的公共行为提取出来,达到复用的目的。而且, 在模板方法模式中,是由父类的模板方法来控制子类中的具体实现。这样你在实现子类的时 候,根本不需要对业务流程有太多的了解

十、适配器模式(Adapter)

适配器模式定义:

将一个类的接口转换成客户希望的另外 一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

todo: 待补充

十一、建造者模式(Builder)

将构造复杂对象的过程和组成对象的部件解耦。

/*** 建造者模式* * @author Mona**/
class User{private String name;private String password;private String nickName;private int age;//构造方法私有化,不然客户端就会直接调用构造方法了private User(String name,String password,String nickName,int age) {this.name = name;this.password = password;this.nickName = nickName;this.age = age;}//静态方法,用于生成一个Builder,这个不一定要有,不够写这个方法是一个很好的习惯//有些代码要求别人写new User.UserBuilder().a()...build()栏上去就没有那么好public static UserBuilder builder() {return new UserBuilder();}public static class UserBuilder{private String name;private String password;private String nickName;private int age;private UserBuilder() {}public UserBuilder name(String name) {this.name = name;return this;}public UserBuilder password(String password) {this.password = password;return this;}public UserBuilder nickName(String nickName) {this.nickName = nickName;return this;}public UserBuilder age(int age) {this.age = age;return this;}public User build() {if(name == null || password == null) {throw new RuntimeException("用户名和密码必填");}if(age <= 0 || age >= 150) {throw new RuntimeException("年龄不合法");}if(nickName == null) {nickName = name;}return new User(name, password, nickName, age);}}
}public class BuilderUser {public static void main(String[] args) {User d = User.builder().name("foo").password("pass12345").age(25).build();}
}

参考文章:初探Java设计模式2:结构型模式(代理模式,适配器模式等)_黄小斜学Java-CSDN博客

java开发中的常用的设计模式_不远阑珊处的博客-CSDN博客_java常见设计模式

Java设计模式(方法工厂类、单例模式、代理模式、策略模式、适配器、观察者、装饰类等)相关推荐

  1. java设计模式之工厂模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  2. Java设计模式之工厂模式 (工厂方法模式)

    上一篇我们学习了简单工厂模式,最后对于增加新产品的缺点,我们在工厂方法模式中解决. 为学习简单工厂模式的小伙伴点击这里Java 设计模式之工厂模式(简单工厂模式) 工厂方法模式要点: 避免简单工厂模式 ...

  3. 一文叫你弄懂Java设计模式之工厂方法模式:图解+日志记录器代码实例

    文章目录 详解Java设计模式之工厂方法模式 案例引入工厂方法模式 工厂方法模式 定义 案例分析 UML类图分析 代码分析 工厂方法的重载 工厂方法的隐藏 模式优点 模式缺点 模式适用环境 详解Jav ...

  4. Java设计模式之结构型:代理模式

    前言: 我们一般在租房子时会去找中介,为什么呢?因为你对该地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你做:再比如我们打官司需要请律师,因为律师在法律方面有专长,可以替我们进行操作,表达我们 ...

  5. Java 设计模式之工厂模式(二)

    原文地址:Java 设计模式之工厂模式(二) 博客地址:http://www.extlight.com 一.背景 本篇内容是 Java 设计模式创建型模式的第二篇.上一篇主题为 <Java 设计 ...

  6. Java设计模式之 工厂模式(简单工厂模式)

    前一阵子学习了Java 中据说是最简单的设计模式的 单例模式,想一起讨论学习的小伙伴请点击这里: Java 设计模式之单例模式 那么今天就把学习的工厂模式记录下来 工厂模式: 实现了创建者和调用者的分 ...

  7. Java设计模式(工厂模式>抽象工厂模式和原型模式)

    Java设计模式Ⅱ 1.工厂模式 1.1 简单工厂模式 1.2 工厂方法模式 2.抽象工厂模式 3.总结 4.原型模式 4.1 原型模式 4.2 浅拷贝 4.3 深拷贝 5.建造者模式 1.工厂模式 ...

  8. Java设计模式之工厂模式篇 (转)

    Java设计模式之工厂模式篇 (转)[@more@]Java设计模式之工厂模式篇 作者:冯睿  本文选自:赛迪网 2003年03月07日 .NET.com.cn/servlets/ad?Pool=te ...

  9. 【JAVA进阶系列】JAVA 设计模式 -- 抽象工厂模式(Abstract Factory)

    [JAVA进阶系列]JAVA 设计模式 -- 抽象工厂模式(Abstract Factory) [1.1]抽象工厂模式简介 抽象工厂者模式的类结构图 AbstractProduct(抽象产品),Abs ...

  10. Java 设计模式归纳(观察者、工厂、单例、策略、适配器、命令、装饰者、外观、模板方法、状态

    DesignPattern 项目地址:youlookwhat/DesignPattern  简介: Java 设计模式归纳 (观察者.工厂.单例.策略.适配器.命令.装饰者.外观.模板方法.状态). ...

最新文章

  1. 跨域产生的原因及解决方法
  2. RabbitMQ消息自动重新入队
  3. WPF使用Animation仿WeChat(微信)播放语音消息
  4. 1071svm函数 r语言_R语言机器学习之核心包e1071 - 数据分析
  5. 信息学奥赛一本通C++语言——1086:角谷猜想
  6. js+css淡入效果
  7. 跨境电商独立站是什么意思?
  8. spring security 的 logout 功能
  9. ad20如何画出pcb板大小_PCB板过孔对高频信号传输的影响,一定要重视
  10. 趋势 | 或许,这就是大佬吧!——美国ETF产业三巨头格局浅谈
  11. 【DL小结1】DL入门
  12. c语言课后答案详解,c语言课后练习题答案详解_0.doc
  13. 拼插机器人课和围棋课_乐高机器人玩具与机器人教育有什么区别?
  14. 数字谐音记忆编码连连看网页应用
  15. Meyer Burger获中国客户1800万瑞士法郎光伏设备订单
  16. Android 按钮点击设置静音
  17. IOS(iphone,ipad,itouch)开发 之 屏幕旋转
  18. eve模拟器上虚拟服务器,没有真机怎么做实验?EVE模拟器了解一下
  19. 2022年康复医学治疗技术(师)考试题库
  20. cogs 1487 麻球繁衍

热门文章

  1. 无处不在的传感器,物联网到底是什么?
  2. [个人疑问]为什么列表转集合后其长度的地址时变时不变?(未解决)
  3. 宝讯网捷:抖音618活动有什么玩法?
  4. 服务铝料门窗基本资料
  5. 戴尔r720服务器开机无信号输出,RE: R720服务器故障,不会排除,第一次用戴尔的服务器不会排除故障,求教,谢谢!...
  6. 使用 SSHFS 挂载远程的 Linux 文件系统及目录
  7. UML交互图 -- 时序图 协作图详解
  8. 清华大学计算机学院科研经费,太烧钱!985工程大学年度科研经费统计,看了数据吓一跳!...
  9. Python-读取PDF文件显示在窗口上-Pdf阅读器
  10. 突发奇想 整个智能浇花系统给老妈 浇花用 分享每日过程和经历