# WorkPlace **Repository Path**: yangsongsong/WorkPlace ## Basic Information - **Project Name**: WorkPlace - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-01-24 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # WorkPlace 个人练习项目workplace目录 #DesignPattern-设计模式代码 # Java常用的设计模式 ## 单例模式 https://www.cnblogs.com/restartyang/articles/7770856.html https://www.cnblogs.com/cr330326/p/5627658.html 单例模式是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器中,该服务器的配置信息存在一个文件中,这些配置数据由一个单例对象统一读取,然后服务器进程中的其他对象通过这个单例对象获取配置信息。这种方式简化了在复杂环境下的配置的配置管理。 ### 实现思路: 一个类能返回对象的引用和一个获取该实例的方法(必须是静态的,通常使用getInstance这个名称);当我们调用这个方法时如果该类持有的引用不为空返回对就是这个引用,如果类保持的引用为空就创建该类的实例并将该实例赋值给予该类保持的引用;将该类的构造方法定义为私有方法,这样其他处代码就无法通过构造函数来实例化该类对象,只有通过静态方法来得到该类的唯一实例。 ### 单例模式的优点: 1. 防止其他对象对自己的实例化,确保所有的对象都访问同一个实例 2. 单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。 3. 提供对唯一实例的受控访问。 4. 在系统中只有一个对象,因此可以节约系统资源,当需要频创建和销毁单例模式的对象时单例模式无疑提高了系统的性能。 5. 允许可变数目的实例。 6. 避免共享资源多重占用。 ### 单例模式的缺点: 1. 不适用于变化的对象。 2. 由于单例模式中没有抽象层,因此单例模式的扩展很大的难度。 3. 滥用单利模式将带来一些负面问题,如为了节省资源将数据库链接池对象设计为单例模式,可能会导致共享链接池对象的程序过多而出现链接池溢出;如果实例化的对象太长时间不被利用,系统会认为是垃圾而回收,这将导致对象状态丢失。 ### 单例模式使用场景: 1. 资源共享情的况下,避免由于资源操作时导致性能或损耗等。如日志文件,应用配置等。 2. 控制资源的情况下,方便资源之间的相互通信。如线程池等。 ###单例模式应用场景例举: 1. 外部资源:每个计算机由若干个打印机,但只能有一个Printer Spooler,一面两个打印机同时输出到打印机。内部资源:文件属性配置管理程序。 2. 访问量统计 3. 系统的任务管理进程 4. web应用配置对象的读取 5. 数据库连接池 6. 应用程序的日志应用 7. 多线程的线程池一般用单利模式 8. 操作系统的文件系统 9. HttpApplication ### 1、懒汉式 **特点:**单例实例在第一次被使用时创建,延迟初始化。 ``` public class Singleton { /* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */ private static Singleton instance = null; /* 私有构造方法,被防止实例化 */ private Singleton() { } /* 1.懒汉式,静态工程方法,创建实例 */ public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } ``` **优点:**避免没有使用的情况下创建实例,资源利用率不高,不执行getInstance()就不会被实例化。 **缺点:**懒汉式在单线程中没有问题,但是在多线程同时访问的时候就可能同时创建多个实例,而且这个多个实例不是同一个对象,虽然后面的实力会覆盖前面创建的实例,但还是会存在拿不到同一个对象的情况。解决这个问题的方法就是加上所synchonized,第一次加载时不够快,多线程使用不必要的同步开销大。 ### 2、饿汉式 **特点**:单例实例在类装载时就创建,急切初始化。(预先加载法) ``` public class HungrySingleton { /* 私有构造函数 */ private HungrySingleton() {} /* 预先创建实例 */ public static HungrySingleton instance = new HungrySingleton(); /* 获取单例实例静态方法*/ public static HungrySingleton hetInstance() { return instance; } } ``` **优点** 1. 线程安全 2. 在类加载的同时已经创建好一个静态实例,调用时反应速度快。 **缺点** 资源效率不高,可能getInstance()永远不会执行到,但执行该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然初始化 ### 3、双重检测 ``` public class DoubleDetectionSingleton { private static volatile DoubleDetectionSingleton sInst = null; private DoubleDetectionSingleton() {} public static DoubleDetectionSingleton getInstance() { DoubleDetectionSingleton dInst = sInst; if (dInst == null) { synchronized (DoubleDetectionSingleton.class) { dInst = sInst; if (dInst == null) { dInst = new DoubleDetectionSingleton(); sInst = dInst; } } } return dInst; } protected void method() { System.out.println("DoubleDetectionSingleton"); } } ``` **优点**:延迟加载,线程安全 **缺点**:写法复杂,不简洁 ### 4、内部类的实现 ``` public class InnerSingleton { /** * 内部类实现单利模式 延迟加载,减少内存开销 */ private static class SingletonHolder { private static InnerSingleton instance = new InnerSingleton(); } private InnerSingleton() { } public static InnerSingleton getInstance() { return SingletonHolder.instance; } } ``` 优点 资源利用率高,不执行getInstance()不被实例,可以执行该类其他静态方法 缺点 第一次加载时反应不够快 总结: 一般采用饿汉式,若对资源十分在意可以采用静态内部类,不建议采用懒汉式及双重检测 ## 工厂模式 基本概念:为创建对象提供过渡接口,以便将创建对象的具体过程隔离起来,达到提高灵活性的目的。 分为三类: - 简单工厂模式Simple Factory:不利于产生系列产品; - 工厂方法模式Factory Method:又称为多形性工厂 - 抽象工厂模式Abstract Factory:又称为工具箱,产生产品族 ### 简单工厂模式 简单工厂又称为静态工厂方法模式。它存在目的就是定义一个用于创建对象的接口。在简单工厂模式中一个工厂类处于对产品类实例化调用的中心位置上,它决定那一个产品类应当被实例化 #### 组成 - 工厂类角色:它是模式的核心,含有一定的商业逻辑和判断逻辑。在Java中往往由一个具体类实现。 - 抽象产品角色:它一般是具体产品的父类或者实现的接口。在Java在由接口或者抽象类来实现。 - 具体产品角色:工厂类所创建的对象就是该具体类的实例。在Java中由一个具体类实现。 抽象角色: ``` public interface Car { void makeCar(); } ``` 具体角色 ``` //简单工厂-具体角色红色Car public class RedCar implements Car { @Override public void makeCar() { System.out.println("生产一辆红色Car"); } } //简单工厂-具体角色白色Car public class WhiteCar implements Car { @Override public void makeCar() { System.out.println("生产一辆白色Car"); } } //简单工厂-具体角色绿色Car public class GreenCar implements Car { @Override public void makeCar() { System.out.println("生产一辆绿色Car"); } } ``` 工厂类 ``` public class CarFactory { public static Car create(int which) { Car car = null; switch (which) { case 1: car = new RedCar(); break; case 2: car = new WhiteCar(); break; case 3: car = new GreenCar(); break; default: System.out.println("没有找到指定类型的汽车"); break; } return car; } public static void main(String[] args) { CarFactory.create(1).makeCar(); CarFactory.create(2).makeCar(); CarFactory.create(3).makeCar(); } } ``` ### 工厂方法模式 工厂方法模式是简单工厂模式的进一步抽象和推广,工厂方法模式里不再只由一个工厂类决定哪一个产品类应该被实例化,这个决定被交给抽象工厂的子类创建。 #### 组成 - 抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关,是具体工厂角色实现接口或者继承的父类。在Java中它由接口和抽象类来实现。 - 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。 - 抽象产品角色:它是具体产品继承的父类或者是实现的接口。在Java一般由抽象类或者接口来实现。 - 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在Java中由具体类来实现。 工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象的承受压力;而且这样使得结构变得灵活起来。 #### 示例代码 **抽象工厂** ``` public abstract class AbstractCarFactory { abstract Car factoryMakeCar(); } ``` **具体工厂类** ``` // 红色Car工厂 public class RedCarFactory extends AbstractCarFactory { @Override public Car makeCar() { System.out.println("红色Car工厂"); return new RedCar(); } } // 白色car工厂 public class WhiteCarFactory extends AbstractCarFactory { @Override Car makeCar() { System.out.println("白色car工厂"); return new WhiteCar(); } } // 绿色car工厂 public class GreenFactory extends AbstractCarFactory { @Override Car makeCar() { System.out.println("绿色car工厂"); return new GreenCar(); } } ``` **测试类** ``` public class Test { public static void main(String[] args) { RedCarFactory redCarFactory = new RedCarFactory(); WhiteCarFactory whiteCarFactory = new WhiteCarFactory(); GreenFactory greenFactory = new GreenFactory(); redCarFactory.factoryMakeCar().makeCar(); whiteCarFactory.factoryMakeCar().makeCar(); greenFactory.factoryMakeCar().makeCar(); } } // 结果 红色Car工厂 生产一辆红色Car 白色car工厂 生产一辆白色Car 绿色car工厂 生产一辆绿色Car ``` 可以看出工厂方法的加如,使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。 ###抽象工厂模式 抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂由成为其他工厂的工厂。这种设计模式属于创建型模式,它提供一种创建对象的最佳方式。允许使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么,这样就可以从具体产品中被解耦。  **组成** - 抽象产品族:抽象产品的父类,描述抽象产品的公共接口。 - 抽象产品:具体产品的父类,描述具体产品的公共接口。 - 具体产品:抽象产品的子类,工厂类创建的目标类。描述生产的具体产品。 - 抽象工厂:具体工厂的父类,描述具体工厂的公共接口。 - 具体工厂:抽象工厂的子类;被外界调用。描述具体工厂;实现工厂方法创建产品的实例。 **优点** 降低耦合 抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展; 更符合开-闭原则 新增一种产品类时,只需要增加相应的具体产品类和相应的工厂子类即可 2.3 使用步骤 步骤1:创建抽象工厂类,定义具体工厂的公共接口; 步骤2:创建抽象产品族类 ,定义抽象产品的公共接口; 步骤3:创建抽象产品类 (继承抽象产品族类),定义具体产品的公共接口; 步骤4:创建具体产品类(继承抽象产品类) & 定义生产的具体产品; 步骤5:创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法; 步骤6:客户端通过实例化具体的工厂类,并调用其创建不同目标产品的方法创建不同具 示例代码: 抽象工厂 ``` public abstract class AbstractFactory { public abstract Color getColor(String color); public abstract Shape getShape(String shape); } ``` 具体形状 ``` // 抽象形状角色 public interface Shape { void draw(); } // 圆形 public class Circle implements Shape { @Override public void draw() { System.out.println("圆形具体类"); } } // 矩形 public class Rectangle implements Shape { @Override public void draw() { System.out.println("矩形具体类"); } } // 形状工厂 public class ShapeFactory extends AbstractFactory { @Override public Color getColor(String color) { return null; } @Override public Shape getShape(String shape) { if (shape.equalsIgnoreCase("CIRCLE")) { return new Circle(); } else if (shape.equalsIgnoreCase("RECTANGLE")) { return new Rectangle(); } return null; } } ``` 具体颜色填充 ``` // 抽象颜色角色 public interface Color { void fill(); } // 红色 public class Red implements Color { @Override public void fill() { System.out.println("红色"); } } // 白色 public class White implements Color { @Override public void fill() { System.out.println("白色"); } } // 绿色 public class Green implements Color { @Override public void fill() { System.out.println("绿色"); } } // 颜色工厂 public class ColorFactory extends AbstractFactory{ @Override public Color getColor(String color) { if (color.equalsIgnoreCase("RED")) { return new Red(); } else if (color.equalsIgnoreCase("WHITE")) { return new White(); } else if (color.equalsIgnoreCase("GREEN")) { return new Green(); } return null; } @Override public Shape getShape(String shape) { return null; } } ``` 调用者 ``` public class FactoryProducer { public static AbstractFactory getFactory(String choice) { if (choice.equalsIgnoreCase("SHAPE")) { return new ShapeFactory(); } else if (choice.equalsIgnoreCase("COLOR")) { return new ColorFactory(); } return null; } } ``` 测试类 ``` public class Test { public static void main(String[] args) { AbstractFactory shapeFactory = FactoryProducer.getFactory("shape"); shapeFactory.getShape("CIRCLE").draw(); shapeFactory.getShape("RECTANGLE").draw(); AbstractFactory colorFactory = FactoryProducer.getFactory("color"); colorFactory.getColor("RED").fill(); colorFactory.getColor("WHITE").fill(); colorFactory.getColor("GREEN").fill(); } } // 结果 圆形具体类 矩形具体类 红色 白色 绿色 ``` ## 观察者模式 1、定义:在对象之间定义了一对多的依赖,这样一来,当一个对象状态改变,依赖它的对象就会收到通知并自动更新。其实就是发布订阅模式,发布者发布消息,订阅者获取信息,订阅了就能收到信息,没有订阅就收不到信息。 2、成员角色  - 抽象被观察角色Subject:也就是一个主体抽象类,它把所有对观察者对象的应用保存在一个集合中,每个主题可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。 - 抽象观察者角色Observer:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。 - 具体被观察者角色:也就是一个具体的主题,在集体主题的内部状态改变时,向所有登记的观察者发出通知。 - 具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。 4、观察者模式具体实现 - 定义抽象被观察者接口 ``` /** *
Title: Subject.java> *
Description: 设计模式-观察者模式:主题接口,定义注册、取消订阅和通知接口 *
Company: YSS * @author yangsongsong * @date 2019年1月8日 */ package com.yss.obsever; public interface Subject { /** * 订阅接口 * * @param observer */ public void registerOberver(Observer observer); /** * 取消订阅接口 * * @param observer */ public void removeObserver(Observer observer); /** * 通知所有订阅者更新接口 */ public void notifyObservers(); } ``` - 定义抽象观察者接口 ``` /** *
Title: Observer.java> *
Description: 设计模式-观察者模式:订阅者抽象类, *
Company: YSS * @author yangsongsong * @date 2019年1月8日 */ package com.yss.obsever; public interface Observer { /** * 更新消息 */ public void update(String message); } ``` - 定义具体被观察者,实现抽象被观察者接口 ``` /** *
Title: ObjectFor3D.java> *
Description: 设计模式-观察者模式:提供3D服务 *
Company: YSS
* @author yangsongsong
* @date 2019年1月8日
*/
package com.yss.obsever;
import java.util.ArrayList;
import java.util.List;
public class ObjectFor3D implements Subject {
/**
* 订阅者集合
*/
private List Title: Oberver1.java>
* Description:设计模式-观察者模式:订阅者
* Company: YSS
* @author yangsongsong
* @date 2019年1月8日
*/
package com.yss.obsever;
public class Oberver1 implements Observer {
@SuppressWarnings("unused")
private Subject mSubject;
/**
* 构造函数
*/
public Oberver1(Subject subject) {
this.mSubject = subject;
subject.registerOberver(this);
}
/*
* 更新消息
*
* @see com.yss.obsever.Observer#update(java.lang.String)
*/
@Override
public void update(String message) {
System.out.println("Oberver1 获取3D号码 -->" + message + "我要记下来");
}
}
```
- 定义观察者2
```
/**
* Title: Oberver2.java>
* Description:设计模式-观察者模式:订阅者2
* Company: YSS
* @author yangsongsong
* @date 2019年1月8日
*/
package com.yss.obsever;
public class Oberver2 implements Observer {
@SuppressWarnings("unused")
private Subject mSubject;
/**
* 构造函数
*/
public Oberver2(Subject subject) {
this.mSubject = subject;
subject.registerOberver(this);
}
/*
* 更新消息
*
* @see com.yss.obsever.Observer#update(java.lang.String)
*/
@Override
public void update(String message) {
System.out.println("Oberver2 获取3D号码 -->" + message + "我要记下来");
}
}
```
- 功能测试类
```
/**
* Title: OberverTest.java>
* Description: 设计模式-观察者模式:测试
* Company: YSS
* @author yangsongsong
* @date 2019年1月8日
*/
package com.yss.obsever;
public class OberverTest {
@SuppressWarnings("unused")
public static void main(String[] args) {
ObjectFor3D objectFor3D = new ObjectFor3D();
Oberver1 oberver1 = new Oberver1(objectFor3D);
Oberver2 oberver2 = new Oberver2(objectFor3D);
objectFor3D.setMessage("20140420的3D号码是:127");
objectFor3D.setMessage("20140421的3D号码是:137");
}
}
```
https://www.cnblogs.com/luohanguo/p/7825656.html
## 建造模式
https://blog.csdn.net/carson_ho/article/details/54910597
#### 概念
建造模式是对象的创建模式。建造可以将一个产品的内部表象与生产过程分割开来,从而可以使一个建造过程生成具有不同内部表象的产品对象。
#### 产品的内部表象
一个产品常有不同的组成成分作为产品的零件,这些零件有可能是对象,也有可能不是对象,它们通常又叫做产品的内部表象。不同的产品有不同的内部表象,也就是不同的零件。使用建造模式可以使客户端不需要知道所有生成的产品有哪些零件,每个产品的对应零件彼此间有何不同,是怎么建造出来的,以及怎么组成产品的。
#### 对象性质的建造
有些情况下,一个对象会有一些重要的性质,在它们没有恰当的值之前,对象不能作为一个完整的产品使用。有些情况下,一个对象的一些性质必须按照某个特定的顺序赋值才有意义。
建造模式是利用一个导演对象和一个具体建造对象一个个地建造出所有的零件,从而建造出完整的产品。
#### 建造模式结构
- **抽象建造者角色**:给出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建产品的对象是具体建造角色。具体建造者类必须继承或者实现接口所要求的两种方法:一种是建造方法,另一种是返回结构方法。
- **具体建造者角色:**担任这个角色的是与应用程序紧密相关的一些类,它们在应用程序调用下创建产品实例,这个角色要完成的任务包括:1.实现抽象建造者Builder所有声明的接口,给出一步一步地完成创建产品实例的操作。2.在建造过程完成后提供产品实例。
- **导演角色**:担任这个角色的类调用具体建造以创建产品对象。应当指出的是,导演角色并没有产品类的具体知识。真正拥有产品类的具体知识的是具体建造者角色。
- **产品角色**:产品便是建造的复杂对象。
**UML类图 & 组成**

### 示例代码
##### 具体产品
```
/**
* Title: Product.java>
* Description: 设计模式-建造者模式:具体的产品对象
* Company: YSS
* @author yangsongsong
* @date 2019年1月9日
*/
package com.yss.builder;
@SuppressWarnings("unused")
public class Product {
private String name;
private String sex;
private int age;
private String address;
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the sex
*/
public String getSex() {
return sex;
}
/**
* @param sex the sex to set
*/
public void setSex(String sex) {
this.sex = sex;
}
/**
* @return the age
*/
public int getAge() {
return age;
}
/**
* @param age the age to set
*/
public void setAge(int age) {
this.age = age;
}
/**
* @return the address
*/
public String getAddress() {
return address;
}
/**
* @param address the address to set
*/
public void setAddress(String address) {
this.address = address;
}
/* toString方法
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Product [name=" + name + ", sex=" + sex + ", age=" + age + ", address=" + address + "]";
}
}
```
##### 抽象建造者
```
/**
* Title: Builder.java>
* Description: 设计模式-建造者模式:抽象建造者
* Company: YSS
* @author yangsongsong
* @date 2019年1月9日
*/
package com.yss.builder;
public interface Builder {
/**
* 建造name接口
*/
public void buildName();
/**
* 建造sex接口
*/
public void buildSex();
/**
* 建造age接口
*/
public void buildAge();
/**
* 建造address接口
*/
public void buildAddress();
/**
* 返回组装好的产品
*
* @return
*/
public Product resultProduct();
}
```
##### 具体建造者
```
/**
* Title: ConcreteBuilder.java>
* Description: 设计模式-建造者模式:具体建造者
* Company: YSS
* @author yangsongsong
* @date 2019年1月9日
*/
package com.yss.builder;
public class ConcreteBuilder implements Builder {
private Product mProduct = new Product();
/*
* 设置姓名
*
* @see com.yss.builder.Builder#buildName()
*/
@Override
public void buildName() {
mProduct.setName("张三");
}
/*
* 设置性别
*
* @see com.yss.builder.Builder#buildSex()
*/
@Override
public void buildSex() {
mProduct.setSex("保密");
}
/*
* 设置年龄
*
* @see com.yss.builder.Builder#buildAge()
*/
@Override
public void buildAge() {
mProduct.setAge(22);
}
/*
* 设置地址
*
* @see com.yss.builder.Builder#buildAddress()
*/
@Override
public void buildAddress() {
mProduct.setAddress("中国北京中关村");
}
/*
* 返回构建的产品
*
* @see com.yss.builder.Builder#resultProduct()
*/
@Override
public Product resultProduct() {
return mProduct;
}
}
```
##### 导演角色
```
/**
* Title: Director.java>
* Description: 设计模式-建造模式:导演角色
* Company: YSS
* @author yangsongsong
* @date 2019年1月10日
*/
package com.yss.builder;
public class Director {
private Builder mbuilder;
/**
* 构造方法传入Builder
*/
public Director(Builder builder) {
this.mbuilder = builder;
}
/**
* 产品建造过程调用
*/
public void construct() {
mbuilder.buildName();
mbuilder.buildSex();
mbuilder.buildAge();
mbuilder.buildAddress();
}
}
```
##### 客户端
```
/**
* Title: Clent.java>
* Description: 设计模式-建造者模式:客户端
* Company: YSS
* @author yangsongsong
* @date 2019年1月10日
*/
package com.yss.builder;
public class Clent {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
// 执行建造
director.construct();
Product product = builder.resultProduct();
System.out.println(product.toString());
}
}
// 结果
Product [name=张三, sex=保密, age=22, address=中国北京中关村]
```
##代理模式
https://blog.csdn.net/nimqbiyq/article/details/81166893
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;既通过代理对象访问目标对象,这样做的好处是可以在目标对象实现的基础上增加额外的功能操作,既扩展目标对象的功能。**简单说就是代理就是增强方法,让方法实现更多额外的功能。**
### 1、静态代理
静态代理通常用于对原有业务逻辑的扩充。
#### 角色
1. 被代理的对象必须是一个类,且必须有父接口或者父类;
2. 被代理的类需要增强的方法必须在父类或者父接口中出现;
3. 静态代理的使用是为类保护和隐藏目标对象,所以代理类的无参构造器中构造目标对象。
#### 实例代码:
```
package com.yss.proxy;
/**
* @author yangsongsong
* @Title: ${Image}>
* @Description:设计模式-静态代理:抽象接口
* @Company: YSS
* @date 2019/1/21:23:04
*/
public interface Image {
void display();
}
```
被带代理的对象,实现Image抽象接口
```
package com.yss.proxy;
/**
* @author yangsongsong
* @Description:juti 设计模式-代理模式:实现Image接口的实体类
* @Company: YSS
* @date 2019/1/21:23:08
*/
public class RealImage implements Image {
private String fileName;
public RealImage(String fileName){
this.fileName = fileName;
loadFormatDisk(fileName);
}
/**
* LoadFormat
* @param fileName
*/
private void loadFormatDisk(String fileName) {
System.out.println("Loading " + fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
}
```
代理类,也需要实现Image抽象接口:
```
package com.yss.proxy;
/**
* @author yangsongsong
* @Description: 设计模式-静态代理模式:代理类
* @Company: YSS
* @date 2019/1/22:0:51
*/
public class ProxyImage implements Image {
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName) {
this.fileName = fileName;
}
@Override
public void display() {
if (realImage == null)
realImage = new RealImage(fileName);
realImage.display();
}
}
```
测试类:
```
package com.yss.proxy;
/**
* @author yangsongsong
* @Description: description
* @Company: YSS
* @date 2019/1/22:0:57
*/
public class ProxyPatternDemo {
public static void main(String[] args) {
Image image = new ProxyImage("test_image.jpg");
image.display();
System.out.println("");
image.display();
}
}
```
输出结果:
> Loading test_image.jpg
Displaying test_image.jpg
Displaying test_image.jpg
#### 缺点
1. 因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多了。
2. 如果代理对象实现的是接口,父接口中增加方法,目标对象和代理对象都需要维护。
**动态代理可以解决以上缺点**
https://www.cnblogs.com/xiaoluo501395377/p/3383130.html
### 动态代理
动态代理也叫做jdk代理,Java底层封装了实现细节,个是固定,代码简单。直接调用java.lang.reflect.Proxy的静态方法newProxyInstance即可。
每一个动态代理类都必须实现InvocationHandler这个接口,并且在每个代理类的实例都关联到一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke方法来进行调用。
```
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
```
三个参数说明
> proxy:指代我们所代理的那个真实对象
> method:指代的时所要调用的真实对象的某个方法的method对象
> args:指的时调用真实对象的某个方法接受的参数
Proxy这个类的作用是用来动态创建一个代理对象的类,它有许多的方法,但是最常用到的时newProxyInstance:
```
public static Object newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h) throws IllegalArgumentException
```
参数说明:
> loader:一个ClassLoader对象,定义了由那个Class Loader对象来对生产的代理进行加载。
> interface:一个Interface对象,表示将要给我需要代理的对象提供的一组什么接口,如果时接口那么这个代理类就宣称它实现了该接口。
> handler:一个InvocationHandler对象,表示的时当我这个动态代理对象在调用方法的时候,会关联到那个一InvocationHandler对象上。
#### 实例代码
定义的动态代理类实现了InvocationHandler接口:
```
package com.yss.proxy.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* version v1.0
* 项目:WorkPlace
* 包名:com.yss.proxy.dynamic
* 功能描述:设计模式-动态代理:实现InvocationHandler的动态代理类
* 作者:杨松松
* 创建时间:2019/1/23 23:08
*/
public class DynamicProxy implements InvocationHandler {
/**
* 接受真实的代理对象变量
*/
private Object image;
/**
* 构造方法
*
* @param image 真实的代理对象
*/
public DynamicProxy(Object image) {
this.image = image;
}
/**
* @param proxy 我们所代理的真实对象
* @param method 所代理的真实对象的某个方法method对象
* @param args 调用真实对象的某个方法所需要的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在代理真实对象前我们可以添加一些自己的操作
System.out.print("before rent house");
System.out.println("Method: " + method);
// 当代理真实对象后的方法时,其实会自动跳转到代理关联的handler对象的invoke方法中
method.invoke(image);
// 代理真实对象后执行我们的操作
System.out.print("after rent house");
return null;
}
}
```
Client类调用动态代理:
```
package com.yss.proxy.dynamic;
import com.yss.proxy.Image;
import com.yss.proxy.RealImage;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* version v1.0
* 项目:WorkPlace
* 包名:com.yss.proxy.dynamic
* 功能描述:设计模式-动态代理:Client类调用动态代理调用真实对象的方法
* 作者:杨松松
* 创建时间:2019/1/23 23:22
*/
public class Client {
public static void main(String[] args) {
Image realImage = new RealImage("fileName");
InvocationHandler handler = new DynamicProxy(realImage);
Image image = (Image) Proxy.newProxyInstance(handler.getClass().getClassLoader(),
realImage.getClass().getInterfaces(), handler);
image.display();
}
}
```
#### 介绍
{**以下是码云平台说明,您可以替换此简介**
码云是开源中国推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
无论是个人、团队、或是企业,都能够用码云实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 码云特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目
5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)