什么是设计模式
设计模式,是一套被重复应用、少数人通晓的、通过分类编目标、代码设计教训的总结。应用设计模式是为了可重用代码、让代码更容易被别人了解、保障代码可靠性、程序的重用性。
为什么要学习设计模式
设计模式的实质是面向对象设计准则的理论使用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充沛了解
- 能够进步程序员的思维能力、编程能力和设计能力。
- 使程序设计更加标准化、代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期。
- 使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。
设计模式分类
大体能够分为三种,每种加起又能够细分为23种。
- 创立型模式,共五种:工厂办法模式、形象工厂模式、单例模式、建造者模式、原型模式。
- 结构型模式,共七种:适配器模式、装璜器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
- 行为型模式,共十一种:策略模式、模板办法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
设计模式的六大准则
凋谢关闭准则
- 准则思维:尽量通过扩大软件实体来解决需要变动,而不是通过批改已有的代码来实现变动
- 形容:一个软件产品在生命周期内,都会发生变化,既然变动是一个既定的事实,咱们就应该在设计的时候尽量适应这些变动,以进步我的项目的稳定性和灵活性。
- 长处:繁多准则通知咱们,每个类都有本人负责的职责,里氏替换准则不能毁坏继承关系的体系。
里氏代换准则
- 准则思维:应用的基类能够在任何中央应用继承的子类,完满的替换基类。
- 大略意思是:子类能够扩大父类的性能,但不能扭转父类原有的性能。子类能够实现父类的形象办法,但不能笼罩父类的非形象办法,子类中能够减少本人特有的办法。
- 长处:减少程序的健壮性,即便减少了子类,原有的子类还能够持续运行,互不影响。
依赖倒转准则
- 依赖倒置准则的核心思想是面向接口编程.
- 依赖倒转准则要求咱们在程序代码中传递参数时或在关联关系中,尽量援用档次高的形象层类,
- 这个是凋谢关闭准则的根底,具体内容是:对接口编程,依赖于形象而不依赖于具体。
接口隔离准则
- 这个准则的意思是:应用多个隔离的接口,比应用单个接口要好。还是一个升高类之间的耦合度的意思,从这儿咱们看出,其实设计模式就是一个软件的设计思维,从大型软件架构登程,为了降级和保护不便。所以上文中屡次呈现:升高依赖,升高耦合。
- 例如:领取类的接口和订单类的接口,须要把这俩个类别的接口变成俩个隔离的接口
迪米特法令(起码晓得准则)
- 准则思维:一个对象该当对其余对象有尽可能少地理解,简称类间解耦
- 大略意思就是一个类尽量减少本人对其余对象的依赖,准则是低耦合,高内聚,只有使各个模块之间的耦合尽量的低,能力进步代码的复用率。
- 长处:低耦合,高内聚。
繁多职责准则
- 准则思维:一个办法只负责一件事件。
- 形容:繁多职责准则很简略,一个办法 一个类只负责一个职责,各个职责的程序改变,不影响其它程序。 这是常识,简直所有程序员都会遵循这个准则。
- 长处:升高类和类的耦合,进步可读性,减少可维护性和可拓展性,升高可变性的危险。
单例模式
什么是单例
保障一个类只有一个实例,并且提供一个拜访该全局拜访点
那些中央用到了单例模式
- 网站的计数器,个别也是采纳单例模式实现的,否则难以同步
- 应用程序的日志利用,个别也都是单例模式实现,只有一个实例去操作才好,否则内容不好最佳显示。
- 多线程的线程池的设计个别也是采纳单例模式,因为线程池要不便对池中的线程进行管制。
- Windows的工作管理器就是厂房典型的单例模式,他不能关上两个
- Windows的回收站也是经典的单例利用。在整个零碎运行过程中,回收站只能保护一个实例。
单例模式的优缺点
长处
- 在单例模式中,流动的单例只有一个实例,对单例类的所有实例化失去的都是雷同的一个实例。这样就避免其余对象对本人的实例化,确保所有的对象都拜访一个实例。
- 单例模式具备肯定的伸缩性,类本人来管制实例化过程,类就在扭转实例化过程上有相应的伸缩性。
- 提供了对惟一实例的受控拜访。
- 因为在零碎内存中只存在一个对象,因而能够节约系统资源,当须要频繁创立和销毁的对象时单例模式无疑能够提供零碎的性能。
- 容许可变数目标实例。
- 防止对共享资源的多重占用。
毛病
- 不适用于变动的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的谬误,不能保留彼此的状态。
- 因为单例模式中没有形象层,因而单例的扩大有很大的艰难。
- 单例类的职责过重,在肯定程序上违反了“繁多职责准则”。
- 滥用单例将带来一些负面问题,如为了节俭资源将数据库连接池对象设计为单例类,可能会导致共享连接池对象的程序过多而呈现连接池溢出;如果实例化的对象长时间不被利用,零碎会认为是垃圾而被回收,这将导致对象状态的失落。
单例模式应用注意事项
- 应用时不能用反射模式创立单例,否则会实例一个新的对象。
- 应用懒单例模式时留神线程平安问题。
- 饿单例模式和懒单例模式构造方法都是公有的,因而是不能被继承的,有些单例模式能够被继承(如注销式模式)
单例避免反射破绽攻打
private static boolean flag = false;private Singleton() { if (flag == flase) { flag = !flag; } eLse { thrown new RuntimeException("单例模式被进犯!"); }}
如何抉择单例创立形式
如果不须要提早加载单例,能够应用枚举或者饿汉式,相对来说枚举性好于饿汉式。如果须要提早加载,能够应用动态外部类或者懒汉式,相对来说动态外部类好于懒汉式。
单例创立形式
- 饿汉式:类初始化时,会立刻加载该对象,线程天生平安,调用效率高。
- 懒汉式:类初始化时,不会初始化该对象,真正须要应用的时候才会创立该对象,具备懒加载性能。
- 动态外部形式:联合了懒汉式和饿汉式格子的长处,真正须要对象的时候才会加载,加载相似线程平安的。
枚举单例:应用枚举实现单例模式
- 长处:实现简略、调用效率高,枚举自身就是单例,因为JVM从根本上提供保障!防止通过反射和反序列化的破绽
- 毛病:没有提早加载
- 双重检测锁形式:因为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从根本上提供保障!防止通过反射和反序列化的破绽
毛病:没有提早加载
工厂模式
什么是工厂模式
它提供了一种创建对象的最佳形式。在工厂模式中,咱们创建对象时不会对客户端裸露创立逻辑,并且是通过应用一个独特的接口来指向新创建的对象。实现了创建者和调用者拆散,工厂模式分为简略工厂、工厂办法、形象工程模式
工厂模式益处
- 工厂模式时咱们最罕用的实例化对象模式了,是用工厂办法代替new操作的一种模式。
- 利用工厂模式能够升高程序的耦合性,为前期的保护批改提供了很大的便当。
- 将抉择实现类、创建对象对立治理和管制。从而将调用者跟我妈的实现类解耦。
Spring开发中的工厂设计模式
Spring IOC
- 看过Spring源码就晓得,在SpringIOC容器创立bean的过程是应用了工厂设计模式。
- Spring中无论是通过xml配置还是通过配置类还是通过注解进行创立bean,大部分都是通过简略工厂来进行创立的。
- 当容器拿到了beanName和class类型后,动静的通过反射创立具体的某个对象,最初将创立的指向放到map中。
为什么Spring IOC 要应用工厂设计模式创立Bean呢?
- 在理论开发中,如果咱们A对象调用B,B调用C,C调用D的话咱们程序的耦合性就会变高。
- 在很久以前的三层架构编程时,都是管制层调用业务层,业务层调用数据拜访层时,都是间接new对象,耦合性大大晋升,代码反复量很高,对象满天飞。
- 为了防止这种状况,Spring应用工厂模式编程,写一个工厂,由工厂创立Bean,当前咱们如果要对象就间接管工厂要就能够了,剩下的事件不归咱们管了.Spring IOC容器的工厂中有个动态的Map汇合,是为了让工厂合乎单例设计模式,即每个对象只生产一次,生产出对象后就存入到Map汇合中,保障了实例不会反复影响程序效率。
工厂模式分类
- 简略工厂:用来生产同一等级构造中的任意产品
- 工厂办法:用来生产同一等级构造中的固定产品
- 形象工厂:用来生产不同产品组族的全副产品。
简略工厂模式
什么是简略工厂模式
简略工厂模式相等于是一个工厂中有各种产品,创立在一个类中,客户无需晓得具体产品的名称,只须要晓得产品类说对应失去参数即可。然而工厂的职责过重,而且当类型过多时不利于零碎的扩大保护。
代码演示:
创立工厂
public interface Car {public void run();}
创立工厂的产品(如果为宝马)
public class Bmw implements Car {@Overridepublic void run() { System.out.println("我是宝马汽车......"); }}
创立工厂中的另外一种产品(如果为奥迪)
public class AoDi implements Car{@Overridepublic void run() { System.out.println("我是奥迪汽车......"); }}
创立外围工厂类,有他决定具体调用哪个产品
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; }}
演示创立工厂的具体实例
public class Client01 {public static void main(String[] args) { Car aoDi = CarFactory.createCar("奥迪"); Car bmw = CarFactory.createCar("宝马"); aoDi.run(); bmw.run();; }}
单工厂的长处/毛病:
长处:简略工厂模式可能依据外界给定的信息,决定到底应该创立哪个具体类的对象。明确辨别了各自的职责和势力,有利于整个软件体系结构的优化。
毛病:很显著工厂类集中了所有实例的创立逻辑,容易违反高汇集的责任分配原则。
工厂办法模式
什么是工厂办法模式
工厂办法模式,又称为多态性工厂模式。在工厂办法模式中,外围的工厂类不在负责所有的产品的创立,而是将具体创立的工作交给子类去做。该外围类成为一个形象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类该当被实例化的这种细节。
代码演示:
创立工厂:
public interface Car {public void run();}
创立工厂办法调用接口(所有的产品须要new进去必须继承他来实现办法)
public interface CarFactory {Car createCar();}
创立工厂的第一种产品(假如为奥迪)
public class AoDi implements Car{@Overridepublic void run() { System.out.println("我是奥迪汽车......"); }}
创立工厂中的另外一个产品(假如为宝马)
public class Bmw implements Car{@Overridepublic void run() { System.out.println("我是宝马汽车......"); }}
创立工厂办法调用接口的实例(奥迪)
public class AoDiFactory implements CarFactory{@Overridepublic Car createCar() { return new AoDi(); }}
创立工厂办法调用接口的实例(宝马)
public class BmwFactory implements CarFactory{@Overridepublic Car createCar() { return new Bmw(); }}
演示创立工厂的具体实例
public class Client {public static void main(String[] args) { Car aodi = new AoDiFactory().createCar(); Car bmw = new BmwFactory().createCar(); aodi.run(); bmw.run(); }}
形象工厂模式
什么是形象工厂模式
形象工厂简略地说是工厂的工厂,形象工厂能够创立具体工厂,由具体工厂来产品具体产品。
代码演示:
创立第一个子工厂,及实现类
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("摩拜"); }}
创立第二个子工厂,及实现类
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("转的慢!"); }}
创立一个总工厂,及实现类(由总工厂的实现类决定调用那个工厂的那个实例)
public interface TotalFactory {// 创立汽车Car createChair();// 创立发动机Engine createEngine();}class TotalFactoryReally implements TotalFactory { public Engine createEngine() { return new EngineA(); } public Car createChair() { return new CarA(); }}
运行测试
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(); }}
代理模式
什么是代理模式
- 通过代理管制对象的拜访,能够在这个对象调用办法之前、调用办法之后去解决/增加新的性能。(也就是AOP的微实现)
- 代理在原有代码乃至原业务流程都不批改的状况下,间接在业务流程中切入行新代码,减少新性能,这也和Spring(面向切面编程)很类似。
代理模式利用场景
Spring AOP、日志打印、异样解决、事务管制、权限管制等等
代理的分类
- 动态代理(动态定义代理类)
- 动静代理(动静生成代理类,也称为JDK自带动静代理)
- Cglib、javaassist(字节码操作库)
三种代理的区别
- 动态代理:简略代理模式,是动静代理的实践根底。常见应用在代理模式。
- JDK动静代理:应用反射实现代理。须要有顶层接口能力应用,常见是myabtis的mapper文件是代理。
- 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(); }}
建造者模式
什么是建造者模式
- 建造者模式:是将一个简单的对象的构建与它的示意拆散,使得同样的构建过程能够创立不同的形式进行创立。
- 工厂类模式提供的是创立单个类的产品,而建造者模式这是将各种产品集中起来进行治理,用来具备不同的属性的产品。
建造者模式通常包含上面几个角色
- Builder:给出一个形象接口,以标准产品对象的各个组成成分的建造。这个接口规定要实现简单对象的哪些局部的创立,并不波及具体的对象部件的创立。
- ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化简单对象的各局部的创立。在建造过程实现后,提供产品的实例。
- Director:调用具体建造者来创立简单对象的各个局部,在指导者中不波及具体产品的信息,只负责保障对象各局部残缺创立或按某种程序创立。
- Product:要创立的简单对象
建造者模式的应用场景
应用场景
- 须要生成的对象具备简单的内部结构。
- 须要生成的对象外部属性自身相互依赖。
- 与工厂模式的区别是:建造者模式更加关注与整机拆卸的程序。
- Java中的StringBuilder就是建造者模式创立的,他吧一个单个只剩的char数组组合起来。
- Spring不是建造者模式,他提供的操作应该是对于字符串自身的一些操作,而不是创立或扭转一个字符串。
代码演示:
建设一个配备对象Arms
import lombok.Data;/** * 配备类 */@Datapublic class Arms { // 头盔 private String helmet; // 铠甲 private String armor; // 武器 private String weapon;}
创立Builder接口(给出一个形象接口,以标准产品对象的各个组成成分的建造,这个接口只是标准)
public interface PersonBuilder {void builderHelmetMurder();void builderArmorMurder();void builderWeaponMurder();void builderHelmetYanLong();void builderArmorYanLong();void builderWeaponYanLong();// 组装Arms builderArms();}
创立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; }}
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());}
模板办法模式
什么是模板办法
模板办法模式:定义一个操作中的算法骨架(父类),而将一些步骤提早到子类中。模板办法是得子类能够不扭转一个算法的构造来重定义该算法的。
什么时候应用模板办法
实现一些操作时,整体步骤很固定,然而呢。就是其中一小部分须要扭转,这时候能够应用模板办法模式,将容易变的局部形象进去,供子类实现。
理论开发中利用场景哪里用到了模板办法
- 其实很多框架中都有用到了模板办法模式
- 例如:数据库拜访的封装、Junit单元测试、servlet中对于doGet/doPost办法的调用等等
现实生活中的模板办法
例如:去餐厅吃饭,餐厅给咱们提供了一个模板就是:看菜单、点菜、吃饭、付款、走人(这里“点菜和付款”是不确定的由子类来实现的,其余的则是一个模板)
代码演示:
先定义一个模板,把模板中的点菜和付款,让子类来实现。
/** * 模板办法 */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(); }}
具体的模板办法子类one
public class RestaurantLobsterImpl extends RestaurantTemplate{ /** * 点菜业务 */ @Override void spotMenu() { System.out.println("龙虾"); } /** * 付款业务 */ @Override void payment() { System.out.println("50块"); }}
具体的模板办法子类two
public class RestaurantGinsengImpl extends RestaurantTemplate{ /** * 点菜业务 */ @Override void spotMenu() { System.out.println("人参"); } /** * 付款业务 */ @Override void payment() { System.out.println("5块"); }}
客户端测试
public class Client { public static void main(String[] args) { RestaurantLobsterImpl restaurantLobster = new RestaurantLobsterImpl(); restaurantLobster.process(); }}
外观模式
什么是外观模式
- 外观模式:也叫门面模式,暗藏零碎的复杂性,并向客户端提供了一个客户端能够拜访零碎的接口。
- 它向现有的零碎增加一个接口,用这一个接口来暗藏理论的零碎的复杂性。
- 应用外观模式,他内部看起来就是一个接口,其实他的外部有很多简单的接口曾经被实现。
代码演示:
用户注册完之后,须要调用阿里短信接口、邮件接口、微信推送接口。
创立阿里短信接口
/** * 阿里短信音讯 */public interface AliSmsService { void sendSms();}
public class AliSmsServiceImpl implements AliSmsService{ @Override public void sendSms() { System.out.println("阿里短信音讯"); }}
创立邮件接口
/** * 发送邮件音讯 */public interface EamilSmsService { void sendSms();}
public class EamilSmsServiceImpl implements EamilSmsService{ @Override public void sendSms() { System.out.println("发送邮件音讯"); }}
创立微信推送接口
/** * 微信音讯推送 */public interface WeixinSmsService { void sendSms();}
public class WeiXinSmsServiceImpl implements WeixinSmsService{ @Override public void sendSms() { System.out.println("发送微信音讯推送"); }}
创立门面(门面看起来很简略,简单的货色以及被门面给封装好了)
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(); }}
进行测试
public class Client { public static void main(String[] args) { new Computer().sendMsg(); }}
原型模式
什么原型模式
- 原型设计模式简略来说就是克隆
- 原型表明了有一个样板实例,这个原型是可定制的。原型模型多用于创立简单的或者结构耗时的实例,因为这种状况下,复制一个曾经存在的实例可使程序运行更高效。
原型模式的利用场景
- 类初始化须要消化十分多的资源,这个资源包含数据、硬件资源等。这时咱们就能够通过原型拷贝防止这些耗费。
- 通过new产生的一个对象须要十分繁琐的数据筹备或者权限,这时能够应用原型模式。
- 一个对象须要提供给其余对象拜访,而且各个调用者可能都须要批改其值时,能够思考应用原型模式拷贝多个对象供调用者应用,即保护性拷贝。
原型模式的应用形式
- 实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时告诉虚拟机能够平安地在实现了此接口的类上应用clone办法。在java虚拟机中,只有实现了这个接口的类才能够被拷贝,否则在运行时会抛出CloneNotSupportedException异样。
- 重写Object类中的clone办法。Java中,所有类的父类都是Object类,Object类中有一个clone办法,作用是返回对象的一个拷贝,然而其作用域protected类型的,个别的类无奈调用,因而Prototype类须要将clone办法的作用域批改为public类型。