什么是设计模式
设计模式,是一套被重复应用、少数人通晓的、通过分类编目标、代码设计教训的总结。应用设计模式是为了可重用代码、让代码更容易被别人了解、保障代码可靠性、程序的重用性。
为什么要学习设计模式
设计模式的实质是面向对象设计准则的理论使用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充沛了解
- 能够进步程序员的思维能力、编程能力和设计能力。
- 使程序设计更加标准化、代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期。
- 使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。
设计模式分类
大体能够分为三种,每种加起又能够细分为 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 { @Override public void run() {System.out.println("我是宝马汽车......"); } }
-
创立工厂中的另外一种产品(如果为奥迪)
public class AoDi implements Car{ @Override public 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{ @Override public void run() {System.out.println("我是奥迪汽车......"); } }
-
创立工厂中的另外一个产品(假如为宝马)
public class Bmw implements Car{ @Override public void run() {System.out.println("我是宝马汽车......"); } }
-
创立工厂办法调用接口的实例(奥迪)
public class AoDiFactory implements CarFactory{ @Override public Car createCar() {return new AoDi(); } }
-
创立工厂办法调用接口的实例(宝马)
public class BmwFactory implements CarFactory{ @Override public 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; /** * 配备类 */ @Data public 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 类型。