- 设计模式
- 创建型模式
- 单例模式
**作用:**保证一个类只有一个实例,并且提供一个访问该实例的全局访问点
常见应用场景:
优点:
- 由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式解决
- 单例模式可以在系统设置全局的访问点,优化共享资源访问,例如可以设计一个单例,负责所有数据表的映射处理。
常见的五种单例模式实现: - 主要:
- 饿汉式(线程安全,调用效率高。但是不能延时加载)
public class SingletonDemo01 {
//类初始化时(天然的线程安全)立即加载(没有延时加载的优势--用到的时候再加载)这个对象
private static SingletonDemo01 instance=new SingletonDemo01();
private SingletonDemo01() {
}
//该处不需要加同步方法,方法没有同步,调用效率高
public static /*synchronzied*/SingletonDemo01 getInstance() {
return instance;
}
}
- 懒汉式(线程安全,调用效率不高。但是能延时加载)
public class SingletonDemo02 {
//类初始化时,不初始化这个对象(延时加载,真正用到时再创建)
public static SingletonDemo02 instance;
private SingletonDemo02() {
}
//方法有同步,调用效率低
public static synchronized SingletonDemo02 getInstance() {
if(instance==null) {
instance=new SingletonDemo02();
}
return instance;
}
}
- 其他:
- 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题,不建议使用)
public class SingletonDemo3 {
private static SingletonDemo3 instance = null;
/**
* 只有第一次同步创建,之后就没必要了。由于编译器优化原因和JVM底层内部模型原因。偶尔会出问题,不建议使用
* @return
*/
public static SingletonDemo3 getInstance() {
if (instance == null) {
SingletonDemo3 sc;
synchronized (SingletonDemo3.class) {
sc = instance;
if (sc == null) {
synchronized (SingletonDemo3.class) {
if (sc == null) {
sc = new SingletonDemo3();
}
}
instance = sc;
}
}
}
return instance;
}
private SingletonDemo3() {
}
}
- 静态内部类式(线程安全,调用效率高。但是能延时加载)
public class SingletonDemo04 {
//外部类没有像饿汉式那样的static属性,不会立即加载对象
//只有真正调用getInstance()才会加载静态内部类。加载类时是线程安全的。instance是static final类型保证了内存中只有这样一个实例存在,而且只能被赋值一次,从而保证线程安全
//兼备:线程安全、效率高以及延迟加载的优势
private static class SingletonClassInstance{
private static final SingletonDemo04 instance=new SingletonDemo04();
}
private SingletonDemo04() {
}
public static SingletonDemo04 getInstance() {
return SingletonClassInstance.instance;
}
}
- 枚举单例(线程安全,调用效率高。但是不能延时加载)
public enum SingletonDemo05 {
//这个枚举元素,本身就是单例对象!
//避免了反射(私有构造器也可以访问)以及反序列化的漏洞
//没有延时加载
INSTANCE;
//添加自己需要的操作
public void singletonOperation() {
}
}
选择方式:
- 需要延迟加载:静态内部类 好于 懒汉式;不需要延迟加载:枚举式 好于 饿汉式
单例模式问题 - 反射可以破解上述(除枚举式)实现方式(可以手动在构造器中抛出异常控制)
- 反序列化可以破解上述(除枚举式)实现方式(可以通过定义readResolve()防止获得不同对象,反序列化时如果对象所在的类定义了readResolve()–实际是一种回调,定义返回那个对象)
SingletonDemo06
public class SingletonDemo06 implements Serializable {
//类初始化时,不初始化这个对象(延时加载,真正用到时再创建)
public static SingletonDemo06 instance;
private SingletonDemo06() {
if(instance!=null) {
throw new RuntimeException();
}
}
//方法有同步,调用效率低
public static synchronized SingletonDemo06 getInstance() {
if(instance==null) {
instance=new SingletonDemo06();
}
return instance;
}
//反序列化时,如果定义了readResolve方法,则直接返回此方法指定的对象,而不需要再创建新对象
private Object readResolve() {
return instance;
}
}
public class Client2 {
public static void main(String[] args) throws Exception {
SingletonDemo06 s1=SingletonDemo06.getInstance();
SingletonDemo06 s2=SingletonDemo06.getInstance();
System.out.println(s1);
System.out.println(s2);
//通过反射直接调用私有构造器
/*Class<SingletonDemo06> clazz=(Class<SingletonDemo06>) Class.forName("com.sxt.singleton.SingletonDemo06");
Constructor<SingletonDemo06> c=clazz.getDeclaredConstructor(null);
c.setAccessible(true);//跳过安全检查
SingletonDemo06 s3=c.newInstance();
SingletonDemo06 s4=c.newInstance();
System.out.println(s3);
System.out.println(s4);*/
//SingletonDemo06为懒汉式实现
/**不修改SingletonDemo06构造方法是的运行结果
* com.sxt.singleton.SingletonDemo06@7852e922
com.sxt.singleton.SingletonDemo06@7852e922
com.sxt.singleton.SingletonDemo06@4e25154f
com.sxt.singleton.SingletonDemo06@70dea4e
*/
/**修改SingletonDemo06构造方法if(instance!=null) {
throw new RuntimeException();
}之后运行结果
* com.sxt.singleton.SingletonDemo06@7852e922
com.sxt.singleton.SingletonDemo06@7852e922
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.sxt.singleton.Client2.main(Client2.java:20)
Caused by: java.lang.RuntimeException
at com.sxt.singleton.SingletonDemo06.<init>(SingletonDemo06.java:13)
... 5 more
*/
//通过反序列化的方式构造多个对象
FileOutputStream fos=new FileOutputStream("F:/src/java/a.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(s1);
oos.close();
fos.close();
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("F:/src/java/a.txt"));
SingletonDemo06 s5=(SingletonDemo06)ois.readObject();
System.out.println(s5);
/**
* 运行结果
* com.sxt.singleton.SingletonDemo06@35f983a6
com.sxt.singleton.SingletonDemo06@35f983a6
com.sxt.singleton.SingletonDemo06@1e88b3c
*/
/**
* 加上readResolve方法之后的结果
* com.sxt.singleton.SingletonDemo06@7852e922
com.sxt.singleton.SingletonDemo06@7852e922
com.sxt.singleton.SingletonDemo06@7852e922
*/
}
}
各种实现的效率测试
public class Client3 {
public static void main(String[] args) throws Exception {
long start=System.currentTimeMillis();
int threadNum=10;
//CountDownLatch 同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待
CountDownLatch countDownLatch=new CountDownLatch(threadNum);
for (int i = 0; i < threadNum; i++) {
new Thread(() -> {
for (int j = 0; j < 100000; j++) {
// Object o = SingletonDemo04.getInstance();
Object o = SingletonDemo05.INSTANCE;
}
countDownLatch.countDown();//当前线程调用此方法则计数减一,建议在finally中执行
}).start();
}
countDownLatch.await();//main线程阻塞直到计数器变成0,才会继续往下执行
long end=System.currentTimeMillis();
System.out.println("总耗时:"+(end-start));
}
}
- 工厂模式
工厂模式
- 实现了创建者和调用者的分离
- 详细分类:
- 简单工厂模式:用来生产同一等级结构中的任意产品(对于新增加的产品,需要修改已有代码)
- 工厂方法模式:用来生产同一等级结构中的固定产品(支持新增任意产品)
- 抽象工厂模式:用来生产不同产品族的全部产品(对于新增产品,无能为力;支持新增产品族)
面向对象设计的基本原则 - OCP(开闭原则,Open-Closed Principle):一个软件的实体应当对扩展开放,对修改关闭
- DIP(依赖倒转原则,Dependence Inversion Principle):要针对接口编程,不要针对实现编程
- LoD(迪米特法则,Law of Demeter):只与你直接的朋友通讯,而避免和陌生人通信
核心本质 - 实例化对象,用工厂方法代替new操作
- 将选择实现类、创建对象统一管理和控制。从而将调用者跟我们的实现类解耦
简单工厂模式实现
- 简单工厂模式也叫静态工厂模式,就是工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的实例对象
- 对于增加新产品无能为力,不修改代码的话,无法扩展。
Car 接口
public interface Car {
void run();
}
public class Audi implements Car {
@Override
public void run() {
System.out.println("奥迪在跑!");
}
}
public class Byd implements Car {
@Override
public void run() {
System.out.println("比亚迪在跑!");
}
}
public class CarFactory {
//此代码并没满足开闭原则,因新增车型时需要修改代码,这也是简单工厂模式的问题
//实现方式1:
public static Car creatCar(String type) {
if("奥迪".equals(type)) {
return new Audi();
}else if("比亚迪".equals(type)) {
return new Byd();
}else {
return null;
}
}
//实现方式2:
public static Car createAudi() {
return new Audi();
}
public static Car createByd() {
return new Byd();
}
}
不使用工厂模式:
public class Client01 {//调用者:需要知道Car Audi Byd等信息
public static void main(String[] args) {
Car c1=new Audi();
Car c2=new Byd();
c1.run();
c2.run();
}
}
使用工厂模式:
public class Client02 {//调用者:只需要知道Car CarFactory
public static void main(String[] args) {
Car c1=CarFactory.creatCar("奥迪");
Car c2=CarFactory.creatCar("比亚迪");
c1.run();
c2.run();
}
}
工厂方法模式
public interface CarFactory {
Car createCar();
}
public class AudiFactory implements CarFactory{
@Override
public Car createCar() {
return new Audi();
}
}
public class BydFactory implements CarFactory{
@Override
public Car createCar() {
return new Byd();
}
}
public class Client {
public static void main(String[] args) {
Car c1=new AudiFactory().createCar();
c1.run();
Car c2=new BydFactory().createCar();
c2.run();
}
}
与简单工厂模式的比较
抽象工厂模式
Engine、Seat和Tyre形成产品族,类图中有两个产品族:LuxuryCarFactory创建的高端产品族,LowCarFactory创建的低端产品族
总结
- 建造者模式
建造者模式的本质
示例类图如下:
AirShipDirector用于组装各种组件,AirShipBuilder用于构建各种组件,前者引用后者并对其组装。在AirShipBuilder的实现类中,构建组件时可以与工厂模式结合
- 原型模式
- 通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式
- 原型模式可以和工厂模式一起使用,当工厂模式底层创建对象时可以使用原型模式
简单实现
//Cloneable 标记接口 类似 Serializable
public class Sheep implements Cloneable{
private String sname;
private Date birthday;
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj=super.clone();//直接调用Object对象的clone方法
return obj;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Sheep() {
super();
}
public Sheep(String sname, Date birthday) {
super();
this.sname = sname;
this.birthday = birthday;
}
}
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Date date=new Date(13241234124L);
Sheep s1=new Sheep("少利",date);
System.out.println(s1);
System.out.println(s1.getSname()+"---->"+s1.getBirthday());
Sheep s2=(Sheep) s1.clone();
System.out.println(s2);
//克隆的对象与原对象保持一样的值
System.out.println(s2.getSname()+"---->"+s2.getBirthday());
//可以修改
s2.setSname("多利");
System.out.println(s2.getSname()+"---->"+s2.getBirthday());
//浅克隆时,date发生改变 s1、s2都会发生改变,因其属性都指向date,没有进行克隆
//深克隆时,s1、s2有各自的date值
}
}
在clone中实现深克隆
protected Object clone() throws CloneNotSupportedException {
Object obj=super.clone();//直接调用Object对象的clone方法
//添加如下代码实现深复制(deep clone),取掉该代码为浅复制
Sheep s=(Sheep)obj;
s.birthday=(Date) this.birthday.clone();
return obj;
}
用序列化和反序列化实现深克隆
public class Client3 {
public static void main(String[] args) throws Exception {
Date date = new Date(234114341L);
Sheep s1 = new Sheep("少利", date);
System.out.println(s1);
System.out.println(s1.getSname() + "--->" + s1.getBirthday());
//Sheep2 s2 = (Sheep2) s1.clone();
// 使用序列化和反序列化实现深复制
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(s1);
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis=new ByteArrayInputStream(bytes);
ObjectInputStream ois=new ObjectInputStream(bis);
Sheep s2=(Sheep)ois.readObject();//克隆好的对象
date.setTime(2341241341L);
System.out.println(s1.getSname() + "--->" + s1.getBirthday());
s2.setSname("多利");
System.out.println(s2.getSname() + "-->" + s2.getBirthday());
}
}
- 创建型模式总结
- 结构型模式
- 核心作用:从程序结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题
- 适配器模式
简单实现
- 适配器的实现有两种方式:1、直接继承被适配的类,然后直接通过super调用其中方法,弊端是java单继承 2、通过组合方式,适配器类引用被适配类对象
/**
* 被适配的类
* PS/2键盘(PS/2接口通过适配器连接usb接口的笔记本)
*
*/
public class Adaptee {
public void request() {
System.out.println("可以完成客户请求的需要功能!!");
}
}
public interface Target {
void handleReq();
}
/**
* 客户端类
* 笔记本(PS/2接口通过适配器连接usb接口的笔记本)
*
*/
public class Client {
public void test1(Target t) {
t.handleReq();
}
public static void main(String[] args) {
Client c=new Client();
Adaptee a=new Adaptee();
// Target t=new Adapter();
Target t=new Adapter2(a);
c.test1(t);
}
}
/**
* 适配器(类适配器方式)
* USB与PS/2的转接器
*
*/
public class Adapter extends Adaptee implements Target {
@Override
public void handleReq() {
super.request();
}
}
/**
* 适配器(对象适配器方式,使用了组合跟被适配对象整合)
* USB与PS/2的转接器
* */
public class Adapter2 implements Target {
private Adaptee adaptee;
@Override
public void handleReq() {
adaptee.request();
}
public Adapter2(Adaptee adaptee) {
this.adaptee=adaptee;
}
}
- 代理模式
- 核心作用:通过代理,控制对对象的访问。可以详细控制访问某个(某类)对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理。(即:AOP的微观实现)
- AOP(Aspect Oriented Programming面向切面编程)的核心实现机制
静态代理(static proxy )
简单实现
public interface Star {
/**
* 面谈
*/
void confer();
/**
* 签合同
*/
void signContract();
/**
* 订票
*/
void bookTicket();
/**
* 唱歌
*/
void sing();
/**
* 收钱
*/
void collectMoney();
}
public class ProxyStar implements Star{
private Star star;
public ProxyStar(Star star) {
this.star=star;
}
@Override
public void bookTicket() {
System.out.println("ProxyStar.bookTicket()");
}@Override
public void collectMoney() {
System.out.println("ProxyStar.collectMoney()");
}
@Override
public void confer() {
System.out.println("ProxyStar.confer()");
}
@Override
public void signContract() {
System.out.println("ProxyStar.signContract()");
}@Override
public void sing() {
star.sing();
}
}
public class RealStar implements Star{
@Override
public void bookTicket() {
System.out.println("RealStar.bookTicket()");
}
@Override
public void collectMoney() {
System.out.println("RealStar.collectMoney()");
}@Override
public void confer() {
System.out.println("RealStar.confer()");
}@Override
public void signContract() {
System.out.println("RealStar.signContract()");
}
@Override
public void sing() {
System.out.println("RealStar.sing()");
}
}
public class Client {
public static void main(String[] args) {
Star real=new RealStar();
Star proxy=new ProxyStar(real);
proxy.confer();
proxy.signContract();
proxy.bookTicket();
proxy.sing();
proxy.collectMoney();
}
}
动态代理(dynamic proxy )
JDK自带的动态代理
public class StarHandler implements InvocationHandler{
Star realStar;
public StarHandler(Star realStar) {
super();
this.realStar = realStar;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object object=null;
System.out.println("唱歌前处理");
if(method.getName().equals("sing")) {
object=method.invoke(realStar, args);
}
System.out.println("唱歌后处理");
return object;
}
}
public class Client {
public static void main(String[] args) {
Star realStar =new RealStar();
StarHandler hanlder=new StarHandler(realStar);
Star proxy=(Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[] {Star.class}, hanlder);
proxy.sing();
}
}
- 桥接模式
/**
* 电脑品牌维度
*
*/
public interface Brand {
void sale();
}
class Lenovo implements Brand{
@Override
public void sale() {
System.out.println("销售联想电脑");
}
}
class Hasee implements Brand{
@Override
public void sale() {
System.out.println("销售神舟电脑");
}
}
/**
* 电脑类型维度
*
*/
public class Computer {//不能使用接口因为有一个属性 需要子类访问
protected Brand brand;
public Computer(Brand brand) {
this.brand = brand;
}
public void sale() {
brand.sale();
}
}
class Desktop extends Computer{
public Desktop(Brand brand) {
super(brand);
}
@Override
public void sale() {
super.sale();
System.out.println("销售台式机");
}
}
class Laptop extends Computer{
public Laptop(Brand brand) {
super(brand);
}
@Override
public void sale() {
super.sale();
System.out.println("销售笔记本");
}
}
public class Client {
public static void main(String[] args) {
//销售联想的笔记本电脑
Computer c=new Laptop(new Lenovo());
c.sale();
}
}
- 组合模式
- 组合模式中的“组合”跟之前Java基础中-组合不一样(A类包含B类对象的引用)
- 组合模式十分适合解决树形结构
- 容器、叶子都实现或继承构建,故其有统一的方式处理
//抽象构建
public interface AbstractFile {
void killVirus();//杀毒
}
//叶子
class ImageFile implements AbstractFile{
private String name;
public ImageFile(String name) {
super();
this.name = name;
}
@Override
public void killVirus() {
System.out.println("----图像文件:"+name+",进行查杀----");
}
}
//叶子
class TextFile implements AbstractFile{
private String name;
public TextFile(String name) {
super();
this.name = name;
}
@Override
public void killVirus() {
System.out.println("----文本文件:"+name+",进行查杀----");
}
}
//叶子
class VideoFile implements AbstractFile{
private String name;
public VideoFile(String name) {
super();
this.name = name;
}
@Override
public void killVirus() {
System.out.println("----视频文件:"+name+",进行查杀----");
}
}
//容器
class Folder implements AbstractFile{
private String name;
//存容器构建下面的子节点
private List<AbstractFile> list=new ArrayList<AbstractFile>();
public Folder(String name) {
super();
this.name = name;
}
public void add(AbstractFile file) {
list.add(file);
}
public void remove(AbstractFile file) {
list.remove(file);
}
public AbstractFile getChild(int index) {
return list.get(index);
}
@Override
public void killVirus() {
System.out.println("----文件夹:"+name+",进行查杀");
for(AbstractFile file:list) {
file.killVirus();
}
}
}
public class Client {
public static void main(String[] args) {
AbstractFile f2,f3,f4,f5,f6;
Folder f1=new Folder("我的收藏");
f2=new ImageFile("头像.jpg");
f3=new TextFile("hello.txt");
f1.add(f2);
f1.add(f3);
Folder f11=new Folder("电影");
f4=new VideoFile("我和我的家乡.mp4");
f5=new VideoFile("我和我的祖国.mp4");
f11.add(f4);
f11.add(f5);
f1.add(f11);
f2.killVirus();
f1.killVirus();
}
}
- 装饰模式
public interface ICar {
void move();
}
//ConcreteComponent 具体构建角色(真实对象)
class Car implements ICar{
@Override
public void move() {
System.out.println("陆地上跑!!");
}
}
//Decorator装饰角色
class SuperCar implements ICar{
protected ICar car;
public SuperCar(ICar car) {
super();
this.car = car;
}
@Override
public void move() {
car.move();
}
}
//ConcreteDecorator具体装饰对象
class FlyCar extends SuperCar{
public FlyCar(ICar car) {
super(car);
}
public void fly() {
System.out.println("天上飞");
}
@Override
public void move() {
super.move();
fly();
}
}
//ConcreteDecorator具体装饰对象
class WaterCar extends SuperCar{
public WaterCar(ICar car) {
super(car);
}
public void swim() {
System.out.println("水上游");
}
@Override
public void move() {
super.move();
swim();
}
}
//ConcreteDecorator具体装饰对象
class AIrCar extends SuperCar{
public AIrCar(ICar car) {
super(car);
}
public void autoMove() {
System.out.println("自动跑游");
}
@Override
public void move() {
super.move();
autoMove();
}
}
public class Client {
public static void main(String[] args) {
ICar car=new Car();
car.move();
System.out.println("增加----->飞行");
ICar flycar=new FlyCar(car);
flycar.move();
System.out.println("增加----->水上游");
ICar watercar=new WaterCar(flycar);
watercar.move();
}
}
IO类中的装饰模式
总结
装饰模式与桥接模式的区别
- 桥接模式解决多维度继承的问题,装饰模式解决多功能组合的问题
- 外观模式(门面模式)
- 核心:为子系统提供统一的入口,封装子系统的复杂性,便于客户端调用
- 遵循迪米特法则-最少知识原则,一个软件实体应当尽可能少的与其他实体发生相互作用
- 享元模式
享元模式设计思路:
- 创建真实享元对象的工厂类:包含享元池用于存储创建的尚未存在的享元类对象,一般设计成键值对
- 区分内部状态和外部状态,分别设计成不同的类
针对上述五子棋的简单实现
/**
* 享元类 抽象享元类FlyWeight
*
*/
public interface ChessFlyWeight {
void setColor(String c);
String getColor();
void display(Coordinate c);
}
/**
* 具体享元类
* @author yinqq
*
*/
class ConcreteChess implements ChessFlyWeight{
private String color;
public ConcreteChess(String color) {
super();
this.color = color;
}
@Override
public void display(Coordinate c) {
System.out.println("棋子颜色:"+color);
System.out.println("棋子位置:"+c.getX()+"-----"+c.getY());
}
@Override
public String getColor() {
return null;
}
@Override
public void setColor(String c) {
this.color=c;
}
}
/**
* 享元工厂类
*
*/
public class ChessFlyWeightFactory {
//享元池
private static Map<String,ChessFlyWeight> map=new HashMap<String, ChessFlyWeight>();
public static ChessFlyWeight getChess(String color) {
if(map.get(color)!=null) {
return map.get(color);
}else {
ChessFlyWeight cfw=new ConcreteChess(color);
map.put(color, cfw);
return cfw;
}
}
}
/**
* 外部状态 非共享享元类UnSharedConcreteFlyWeight
*
*/
public class Coordinate {
private int x,y;
public Coordinate(int x, int y) {
super();
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
public class Client {
public static void main(String[] args) {
//内部状态共享
ChessFlyWeight chess1=ChessFlyWeightFactory.getChess("黑色");
ChessFlyWeight chess2=ChessFlyWeightFactory.getChess("黑色");
System.out.println(chess1);
System.out.println(chess2);
//外部状态变化
System.out.println("增加外部状态的处理");
chess1.display(new Coordinate(10,10));
chess2.display(new Coordinate(20,20));
}
}
- 行为模式
- 责任链模式
创建责任链模式的关键
- 抽象类:责任链对象,包含后续责任链对象引用
- 责任链的先后关系
举例:公司请假审批
/**
* 抽象类
*
*/
public abstract class Leader {
protected String name;
protected Leader nextLeader;//责任链上的后继对象
public Leader(String name) {
super();
this.name = name;
}
//设置责任链上的后继对象
public void setNextLeader(Leader nextLeader) {
this.nextLeader = nextLeader;
}
/**
* 处理请求的核心的业务方法
* @param request
*/
public abstract void handleRequest(LeaveRequest request);
}
/**
* 主管
*
*/
public class Director extends Leader{
public Director(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if(request.getLeaveDays()<3) {
System.out.println("员工:"+request.getEmpName()+"请假,天数:"+request.getLeaveDays()+",理由:"+request.getReason());
System.out.println("主任:"+this.name+",审批通过!");
}else {
if(this.nextLeader!=null) {
nextLeader.handleRequest(request);
}
}
}
}
/**
* 经理
*
*/
public class Manager extends Leader{
public Manager(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if(request.getLeaveDays()<10) {
System.out.println("员工:"+request.getEmpName()+"请假,天数:"+request.getLeaveDays()+",理由:"+request.getReason());
System.out.println("经理:"+this.name+",审批通过!");
}else {
if(this.nextLeader!=null) {
nextLeader.handleRequest(request);
}
}
}
}
/**
* 封装请假的基本信息
*
*/
public class LeaveRequest {
private String empName;
private int leaveDays;
private String reason;
public LeaveRequest(String empName, int leaveDays, String reason) {
super();
this.empName = empName;
this.leaveDays = leaveDays;
this.reason = reason;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public int getLeaveDays() {
return leaveDays;
}
public void setLeaveDays(int leaveDays) {
this.leaveDays = leaveDays;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
}
/**
* 总经理
*
*/
public class GeneralManager extends Leader{
public GeneralManager(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if(request.getLeaveDays()<30) {
System.out.println("员工:"+request.getEmpName()+"请假,天数:"+request.getLeaveDays()+",理由:"+request.getReason());
System.out.println("总经理:"+this.name+",审批通过!");
}else {
System.out.println("莫非"+request.getEmpName()+"想辞职,居然请假:"+request.getLeaveDays());
}
}
}
public class Client {
public static void main(String[] args) {
Leader director=new Director("张三");
Leader manager=new Manager("李四");
Leader generalManager=new GeneralManager("王五");
//组织责任链对象关系
director.setNextLeader(manager);
manager.setNextLeader(generalManager);
//开始请假操作
LeaveRequest req1=new LeaveRequest("Tom", 1, "回英国老家探亲");
director.handleRequest(req1);
}
}
- 迭代器模式
自定义迭代器
- 迭代器接口
- 具体迭代器,一般为内部类,为外部类服务并可直接操作外部类属性
/**
* 迭代器接口
*
*/
public interface MyIterator {
void first();//将游标指向第一个
void next();//将游标指向下一个
boolean hasNext();//判断是否存在下一个元素
boolean isFirst();
boolean isLast();
Object getCurrentObj();//获取当前游标指向的对象
}
/**
* 自定义的聚合类
*
*/
public class ConcreteMyAggregate {
private List<Object> list=new ArrayList<>();
public ConcreteMyAggregate() {
}
//获得迭代器
public MyIterator createIterator() {
return new ConcreteIterator();
}
public void addObject(Object obj) {
this.list.add(obj);
}
public void removeObject(Object obj) {
this.list.remove(obj);
}
public List<Object> getList() {
return list;
}
public void setList(List<Object> list) {
this.list = list;
}
//内部类:可以直接操作外部类对象的属性和方法,只为外部类提供服务
private class ConcreteIterator implements MyIterator{
private int cursor=0;//定义游标用于记录遍历时的位置
@Override
public void first() {
cursor=0;
}
@Override
public void next() {
if(cursor<list.size()) {
cursor++;
}
}
@Override
public boolean hasNext() {
if(cursor<list.size()) {
return true;
}
return false;
}
@Override
public boolean isFirst() {
return cursor==0?true:false;
}
@Override
public boolean isLast() {
return cursor==(list.size()-1)?true:false;
}
@Override
public Object getCurrentObj() {
return list.get(cursor);
}
}
}
public class Client {
public static void main(String[] args) {
ConcreteMyAggregate cma=new ConcreteMyAggregate();
cma.addObject("aa");
cma.addObject("cc");
cma.addObject("bb");
MyIterator iter=cma.createIterator();
while(iter.hasNext()) {
System.out.println(iter.getCurrentObj());
iter.next();
}
}
}
- 迭代器模式
中介者模式的使用
- 同事接口:内部方法+外部方法(用来调用中介者对象)
- 具体同事类:包含中介者对象的引用+同事接口的具体实现
- 中介者接口:包含方法:注册各个同事对象+调用各个同事对象
- 具体中介者:包含HashMap存储同事对象+中介者接口的具体实现
例如
public interface Mediator {
void register(String name,Department d);
void command(String name);
}
public class President implements Mediator {
private Map<String,Department> map=new HashMap<String,Department>();
@Override
public void command(String dname) {
map.get(dname).selfAction();
}
@Override
public void register(String dname, Department d) {
map.put(dname, d);
}
}
//同事类接口
public interface Department {
void selfAction();//做本部门的事情
void outAction();//向总经理发出申请
}
public class Development implements Department {
private Mediator m;//持有中介者(总经理)的引用
public Development(Mediator m) {
super();
this.m = m;
m.register("development", this);
}
@Override
public void outAction() {
System.out.println("汇报工作!没钱了,需要资金支持!");
}
@Override
public void selfAction() {
System.out.println("专心科研,开发项目!");
}
}
public class Finacial implements Department {
private Mediator m;//持有中介者(总经理)的引用
public Finacial(Mediator m) {
super();
this.m = m;
m.register("finacial", this);
}
@Override
public void outAction() {
System.out.println("汇报工作!钱太多了,怎么花?");
}
@Override
public void selfAction() {
System.out.println("数钱!");
}
}
public class Market implements Department {
private Mediator m;//持有中介者(总经理)的引用
public Market(Mediator m) {
super();
this.m = m;
m.register("market", this);
}
@Override
public void outAction() {
System.out.println("汇报工作!项目承接的进度,需要资金支持");
m.command("finacial");
}
@Override
public void selfAction() {
System.out.println("跑去接项目!");
}
}
public class Client {
public static void main(String[] args) {
Mediator m=new President();
Market market=new Market(m);
Development devp=new Development(m);
Finacial f=new Finacial(m);
market.selfAction();
market.outAction();
}
}
--运行结果:
跑去接项目!
汇报工作!项目承接的进度,需要资金支持
数钱!
- 命令模式
命令模式的实现
- 命令接口
- 具体命令类:包含执行者的引用,通过其找到最终的命令执行者
- 调用者类:包含命令类的引用,通过其执行命令
- 命令执行者类
public interface Command {
/**
* 这个方法是一个返回结果为空的方法
* 实际项目中,可以根据需求设计多个不同的方法
*/
void execute();
}
class ConcreteCommand implements Command{
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
super();
this.receiver = receiver;
}
@Override
public void execute() {
//命令真正执行前或后,执行相关的处理
receiver.action();
}
}
//调用者、发起者
public class Invoke {
private Command command;//可以多条命令 可以通过容器List<Command>容纳很多命令对象,进行批处理
public Invoke(Command command) {
super();
this.command = command;
}
//业务方法,用于调用命令类的方法
public void call() {
command.execute();
}
}
//真正的命令执行者
public class Receiver {
public void action() {
System.out.println("Receiver.action()");
}
}
public class Client {
public static void main(String[] args) {
Command c=new ConcreteCommand(new Receiver());
Invoke i=new Invoke(c);
i.call();
}
}
--运行结果:
Receiver.action()
- 解释器模式
- 访问者模式
- 策略模式strategy
实现策略模式:
- Context类与算法的实现打交道,引用其公共接口的引用
- 客户端与Context交互
public interface Strategy {
public double getPrice(double standardPrice);
}
public class NewCustomerFewStrategy implements Strategy {
@Override
public double getPrice(double standardPrice) {
System.out.println("不打折,原价!");
return standardPrice;
}
}
public class OldCustomerFewStrategy implements Strategy {
@Override
public double getPrice(double standardPrice) {
System.out.println("打八五折!");
return standardPrice * 0.85;
}
}
public class OldCustomerManyStrategy implements Strategy {
@Override
public double getPrice(double standardPrice) {
System.out.println("打八折!");
return standardPrice * 0.8;
}
}
/**
* 负责和具体的策略类交互
* 这样话,具体的算法和直接的客户端调用分离,使得算法可以独立于客户端独立的变化
*
* 如果使用spring的依赖注入功能,还可以通过配置文件,动态的注入不同的策略对象,动态的切换不同的算法
*
*/
public class Context {
private Strategy strategy;//当前采用的算法
//可以通过构造器来注入
public Context(Strategy strategy) {
super();
this.strategy = strategy;
}
//可以通过set方法来注入
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void printPrice(double s) {
System.out.println("您的报价:"+strategy.getPrice(s));
}
}
public class Client {
public static void main(String[] args) {
Strategy s1=new OldCustomerManyStrategy();
Context ctx=new Context(s1);
ctx.printPrice(998);
}
}
- 模板方法模式template method
实现模板方法模式
- 固定的模板-流程+其中易变的部分
- 模板抽象类
- 子类实现具体方法
public abstract class BankTemplateMethod {
public void takeNumber() {
System.out.println("取号排队");
}
//办理具体业务 钩子方法
public abstract void transact();
public void evaluate() {
System.out.println("反馈评分");
}
public final void process() {
this.takeNumber();
this.transact();
this.evaluate();
}
}
public class Client {
public static void main(String[] args) {
BankTemplateMethod btm=new DrawMoney();
btm.process();
System.out.println("---------------------------");
//一般情况下采用匿名内部类
BankTemplateMethod btm2=new BankTemplateMethod() {
@Override
public void transact() {
System.out.println("我要存钱");
}
};
btm2.process();
}
}
class DrawMoney extends BankTemplateMethod{
@Override
public void transact() {
System.out.println("我要取款");
}
}
- 状态模式state
实现状态模式
- 不同状态以及相互间的转换关系
- Context上下文类引用状态接口的引用,其代表当前状态
public interface State {
void handle();
}
/**
* 已预定状态
*
*/
public class BookedState implements State{
@Override
public void handle() {
System.out.println("房间已预定!别人不能定!");
}
}
/**
* 已入住状态
*
*/
public class CheckedInedState implements State{
@Override
public void handle() {
System.out.println("房间已入住!请勿打扰!");
}
}
public class RoomContext {
//如果是银行系统,这个Context类就是账户,根据金额不同切换不同的状态
private State state;
public void setState(State s) {
System.out.println("修改状态!");
this.state=s;
state.handle();
}
}
public class Client {
public static void main(String[] args) {
RoomContext ctx=new RoomContext();
ctx.setState(new FreeState());
ctx.setState(new BookedState());
}
}
- 观察者模式observer
实现观察者模式
- 目标对象
- 观察者对象
- 目标父类,包含公共方法:注册移除观察者对象、通知观察者对象
- 观察者接口,包含公共方法:更新状态
public class Subject {
private List<Observer> list=new ArrayList<Observer>();
public void registerObserver(Observer obs) {
list.add(obs);
}
public void removeObserver(Observer obs) {
list.remove(obs);
}
//通知所有观察者更新状态
public void notifyAllObserver() {
for(Observer obs:list) {
obs.update(this);
}
}
}
public class ConcreteSubject extends Subject{
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
//主题对象(目标对象),请通知所有观察者
this.notifyAllObserver();
}
}
public interface Observer {
void update(Subject subject);
}
public class ObserverA implements Observer{
private int myState;//myState需要跟目标对象的state保持一致
@Override
public void update(Subject subject) {
myState=((ConcreteSubject)subject).getState();
}
public int getMyState() {
return myState;
}
public void setMyState(int myState) {
this.myState = myState;
}
}
public class Client {
public static void main(String[] args) {
//目标对象
ConcreteSubject subject=new ConcreteSubject();
//创建多个观察者
ObserverA obs1=new ObserverA();
ObserverA obs2=new ObserverA();
ObserverA obs3=new ObserverA();
//三个观察者添加到subject观察者对象容器中
subject.registerObserver(obs1);
subject.registerObserver(obs2);
subject.registerObserver(obs3);
//改变subject状态
subject.setState(3000);
//查看观察者的状态变化
System.out.println(obs1.getMyState());
System.out.println(obs2.getMyState());
System.out.println(obs3.getMyState());
}
}
JAVASE自带实现
- java.util.Observable和java.util.Observer
public class ObserverA implements Observer{
private int myState;
@Override
public void update(Observable o, Object arg) {
myState=((ConcreteSubject)o).getState();
}
public int getMyState() {
return myState;
}
public void setMyState(int myState) {
this.myState = myState;
}
}
//目标对象
public class ConcreteSubject extends Observable{
private int state;
public void setState(int state) {
this.state = state;//目标对象的状态发生了变化
setChanged();//表示目标对象已经做了更改
notifyObservers(state);//通知所有观察者
}
public int getState() {
return state;
}
}
public class Client {
public static void main(String[] args) {
// 目标对象
ConcreteSubject subject = new ConcreteSubject();
// 创建多个观察者
ObserverA obs1 = new ObserverA();
ObserverA obs2 = new ObserverA();
ObserverA obs3 = new ObserverA();
// 三个观察者添加到subject观察者对象容器中
subject.addObserver(obs1);
subject.addObserver(obs2);
subject.addObserver(obs3);
// 改变subject状态
subject.setState(3020);
// 查看观察者的状态变化
System.out.println(obs1.getMyState());
System.out.println(obs2.getMyState());
System.out.println(obs3.getMyState());
}
}
- 备忘录模式memento
/**
* 源发器类
*
*/
public class Emp {
private String ename;
private int age;
private double salary;
//进行备忘操作,并返回备忘录对象
public EmpMemento memento() {
return new EmpMemento(this);
}
//进行数据恢复,恢复成指定备忘录对象的值
public void recovery(EmpMemento mmt) {
this.ename=mmt.getEname();
this.age=mmt.getAge();
this.salary=mmt.getSalary();
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Emp(String ename, int age, double salary) {
super();
this.ename = ename;
this.age = age;
this.salary = salary;
}
}
/**
* 备忘录类
*
*/
public class EmpMemento {
private String ename;
private int age;
private double salary;
public EmpMemento(Emp e) {
this.ename=e.getEname();
this.age=e.getAge();
this.salary=e.getSalary();
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
/**
* 负责人类
* 负责管理备忘录对象
*
*/
public class CareTaker {
private EmpMemento memento;
//通过容器可以存储多个备忘点,也可以按照键值对存储
public EmpMemento getMemento() {
return memento;
}
public void setMemento(EmpMemento memento) {
this.memento = memento;
}
}
public class Client {
public static void main(String[] args) {
CareTaker taker=new CareTaker();
Emp emp=new Emp("张三",18,900);
System.out.println("第一次打印对象:"+emp.getEname()+"----"+emp.getAge()+"----"+emp.getSalary());
taker.setMemento(emp.memento()); //备忘一次
emp.setAge(38);
emp.setEname("李四");
emp.setSalary(9000);
System.out.println("第二次打印对象:"+emp.getEname()+"----"+emp.getAge()+"----"+emp.getSalary());
emp.recovery(taker.getMemento());//恢复到备忘录保存的状态
System.out.println("第三次打印对象:"+emp.getEname()+"----"+emp.getAge()+"----"+emp.getSalary());
}
}
--运行结果:
第一次打印对象:张三----18----900.0
第二次打印对象:李四----38----9000.0
第三次打印对象:张三----18----900.0