从程序结构上实现松耦合,从而可以扩大整体的类结构
(1)适配器模式
实现:
使得原本接口不兼容的类可以在一起工作
比如:usb接口和网线接口不兼容,可以利用一个usb转接口使得两个一起工作,所以这个转接口一端得插usb接口,一端得插网线接口。
应用实例:
1、美国电器 110V,中国 220V,就要有一个适配器将 110V 转化为 220V。
2、JAVA JDK 1.1 提供了 Enumeration 接口,而在 1.2 中提供了 Iterator 接口,想要使用 1.2 的 JDK,则要将以前系统的 Enumeration 接口转化为 Iterator 接口,这时就需要适配器模式。 3、在 LINUX 上运行 WINDOWS 程序。
4、JAVA 中的 jdbc。
代码实现:
/***
* 被适配的类
*/
public class Adaptee {
public void request(){
System.out.println("连接网线上网");
}
}
public class Adapter2 implements NetToUsb {
private Adaptee adaptee;
public Adapter2(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void handleRequest() {
adaptee.request();
}
}
package com.study.shejiPattern.adapter;
//客户端类:向上网但是插不上网线
public class Computer {
public void net(NetToUsb adapter){
//上网的具体实现
adapter.handleRequest();
}
public static void main(String[] args) {
//电脑。适配器、网线
Computer computer=new Computer();//电脑
Adaptee adaptee=new Adaptee(); //网线
Adapter adapter=new Adapter(); //适配器
computer.net(adapter);
System.out.println("----用组合---");
Computer computer1=new Computer();//电脑
Adaptee adaptee1=new Adaptee(); //网线
Adapter2 adapter2=new Adapter2(adaptee1);
computer1.net(adapter2);
}
}
//接口转换器的抽象实现
public interface NetToUsb {
public void handleRequest();
}
(2)桥接模式
概念:
将抽象部分与它的实现部分分离,独立地变化
比如品牌和电脑,品牌有Lenovo和apple,电脑有desktop和laptop,可以通过桥接模式进行组装。
一个类中有两个独立变化的维度,且两个维度都需要进行扩展
场景:
java虚拟机实现平台无关性、AWT中的Peer架构、JDBC驱动程序
代码实现
public interface Brand {
void info();
}
public class Apple implements Brand {
@Override
public void info() {
System.out.print("apple");
}
}
package com.study.shejiPattern.bridge;
public class Lenovo implements Brand {
@Override
public void info() {
System.out.print("Lenovo");
}
}
package com.study.shejiPattern.bridge;
public abstract class Computer {
protected Brand brand;
public Computer(Brand brand) {
this.brand = brand;
}
public void info(){
brand.info();
}
}
package com.study.shejiPattern.bridge;
public class Desktop extends Computer {
public Desktop(Brand brand) {
super(brand);
}
@Override
public void info() {
super.info();
System.out.println("台式机");
}
}
package com.study.shejiPattern.bridge;
public class Laptop extends Computer {
public Laptop(Brand brand) {
super(brand);
}
@Override
public void info() {
super.info();
System.out.println("笔记本");
}
}
package com.study.shejiPattern.bridge;
public class Test {
public static void main(String[] args) {
Computer computer=new Laptop(new Apple());
computer.info();
Computer computer1=new Desktop(new Lenovo());
computer1.info();
Computer computer2=new Laptop(new Lenovo());
computer2.info();
}
}
(3)过滤器模式
概念:
实际上就是实现一个过滤的作用
代码实现:
package com.study.shejiPattern.filter;
public class Person {
private String name;
private String gender;
private String maritalStatus;
public Person(String name,String gender,String maritalStatus){
this.name = name;
this.gender = gender;
this.maritalStatus = maritalStatus;
}
public String getName() {
return name;
}
public String getGender() {
return gender;
}
public String getMaritalStatus() {
return maritalStatus;
}
}
package com.study.shejiPattern.filter;
import java.util.ArrayList;
import java.util.List;
public class CriteriaMale implements Criteria {
@Override
public List<Person> meetCriteria(List<Person> personList) {
List<Person> malePerson=new ArrayList<>();
for (Person person : personList) {
if(person.getGender().equalsIgnoreCase("male")){
malePerson.add(person);
}
}
return malePerson;
}
}
package com.study.shejiPattern.filter;
import java.util.ArrayList;
import java.util.List;
public class CriteriaSingle implements Criteria {
@Override
public List<Person> meetCriteria(List<Person> personList) {
List<Person> singlePerson=new ArrayList<>();
for (Person person : personList) {
if(person.getMaritalStatus().equalsIgnoreCase("SINGLE")){
singlePerson.add(person);
}
}
return singlePerson;
}
}
package com.study.shejiPattern.filter;
import java.util.List;
public interface Criteria {
public List<Person> meetCriteria(List<Person> personList);
}
package com.study.shejiPattern.filter;
import java.util.ArrayList;
import java.util.List;
public class TestDemo {
public static void main(String[] args) {
Person person=new Person("111","male","single");
Person person1=new Person("222","male1","single1");
Person person2=new Person("333","male","single1");
Person person3=new Person("444","male1","single1");
Person person4=new Person("555","male1","single1");
Person person5=new Person("666","male","single");
List<Person> personList=new ArrayList<>();
List<Person> malePerson=new ArrayList<>();
List<Person> single=new ArrayList<>();
personList.add(person);
personList.add(person1);
personList.add(person2);
personList.add(person3);
personList.add(person4);
personList.add(person5);
Criteria criteriaMale=new CriteriaMale();
Criteria criteriaSingle=new CriteriaSingle();
malePerson=criteriaMale.meetCriteria(personList);
single=criteriaSingle.meetCriteria(personList);
System.out.println("---------male----");
for (Person malePerson1 : malePerson) {
System.out.println(malePerson1.getName()+malePerson1.getGender());
}
System.out.println("---------single-----");
for (Person person6 : single) {
System.out.println(person6.getName()+person6.getMaritalStatus());
}
}
}
(4)组合模式
概念:
主要是用于表示树形结构,比如子文件夹,部门结构之类的
实际上就是在一个List集合里面还可以存在一个list集合
这里的代码比较简单就贴一下一个部门类的实现吧:
主要就是在里面还存在一个list集合
import java.util.ArrayList;
import java.util.List;
public class Employee {
private String name;
private String dept;
private int salary;
private List<Employee> subordinates;
//构造函数
public Employee(String name,String dept, int sal) {
this.name = name;
this.dept = dept;
this.salary = sal;
subordinates = new ArrayList<Employee>();
}
public void add(Employee e) {
subordinates.add(e);
}
public void remove(Employee e) {
subordinates.remove(e);
}
public List<Employee> getSubordinates(){
return subordinates;
}
public String toString(){
return ("Employee :[ Name : "+ name
+", dept : "+ dept + ", salary :"
+ salary+" ]");
}
}
(5)装饰器模式
概念:
一个类想要扩展其功能,但是可以不改变原来的代码。
就像:本来想画一个圆,然后想画一个红色的圆。可以不改变原来画圆的代码,利用装饰模式向上面再装饰一个红色。
代码实现:
package com.study.shejiPattern.decorator; public interface Shape { void draw(); }
package com.study.shejiPattern.decorator;
public class CircleShape implements Shape {
@Override
public void draw() {
System.out.println("circle");
}
}
package com.study.shejiPattern.decorator;
public class RectangleShape implements Shape {
@Override
public void draw() {
System.out.println("rectangle");
}
}
package com.study.shejiPattern.decorator;
/***
* 装饰的抽象类
* 装饰有多种多样
* :用一个抽象类表示共同的
* 具体实现继承就行
*/
public abstract class ShapeDecorator implements Shape{
private Shape decoratorShape; //需要装饰的类
public ShapeDecorator(Shape decoratorShape) {
this.decoratorShape = decoratorShape;
}
@Override
public void draw() {
decoratorShape.draw();
}
}
package com.study.shejiPattern.decorator;
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratorShape) {
super(decoratorShape); //需要装饰的类
}
@Override
public void draw() {
super.draw();
System.out.println("red"); //装饰的操作主要是这个
}
}
package com.study.shejiPattern.decorator;
public class BlueShapeDecorator extends ShapeDecorator {
public BlueShapeDecorator(Shape decoratorShape) {
super(decoratorShape);
}
@Override
public void draw() {
super.draw();
System.out.println("blue");
}
}
package com.study.shejiPattern.decorator;
public class TestDemo {
public static void main(String[] args) {
Shape circle=new CircleShape();
Shape rectangle=new RectangleShape();
System.out.println("------before");
circle.draw();
rectangle.draw();
ShapeDecorator red=new RedShapeDecorator(circle);
ShapeDecorator blue=new BlueShapeDecorator(circle);
ShapeDecorator red1=new RedShapeDecorator(rectangle);
System.out.println("---------after--");
red.draw();
blue.draw();
red1.draw();
// ShapeDecorator blue1=new BlueShapeDecorator(circle);
}
}
(6)外观模式
概念:
主要是提供了一个统一的接口供外部接口访问
比如:有一个形状类,有圆形、矩形等,圆形矩形里面提供方法画,可以通过一个共同的外部接口访问Shape类,就可以不同每次new一个圆形,每次new一个矩形
public class ShapeMaker { private Shape circle; private Shape rectangle; private Shape square; public ShapeMaker() { circle = new Circle(); rectangle = new Rectangle(); square = new Square(); } public void drawCircle(){ circle.draw(); } public void drawRectangle(){ rectangle.draw(); } public void drawSquare(){ square.draw(); } }
public class FacadePatternDemo {
public static void main(String[] args) {
ShapeMaker shapeMaker = new ShapeMaker();
shapeMaker.drawCircle();
shapeMaker.drawRectangle();
shapeMaker.drawSquare();
}
}
(7)享元模式
概念:
减少创建对象的数量,尝试用现有的对象,如果未找到匹配的对象再创建新的对象。(用共享技术有效支持大量细粒度的对象)
主要解决:重复对象的内存浪费问题
在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
何时使用: 1、系统中有大量对象。 2、这些对象消耗大量内存。 3、这些对象的状态大部分可以外部化。 4、这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。 5、系统不依赖于这些对象身份,这些对象是不可分辨的。
如何解决:用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象。
关键代码:用 HashMap 存储这些对象。
应用实例: 1、JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。 2、数据库的数据池。
优点:大大减少对象的创建,降低系统的内存,使效率提高。
代码实现:
package com.study.shejiPattern.share;
public interface Shape {
void draw();
}
package com.study.shejiPattern.share;
public class Circle implements Shape {
private String color;
private int x;
private int y;
private int radius;
public Circle(String color){
this.color = color;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setRadius(int radius) {
this.radius = radius;
}
@Override
public void draw() {
System.out.println("Circle: Draw() [Color : " + color
+", x : " + x +", y :" + y +", radius :" + radius);
}
}
package com.study.shejiPattern.share;
import java.util.HashMap;
/***
* 创建circle对象的工产
* 对于hashMap进行存储
* 如果存在对象就直接返回
* 如果不存在对象就new一个对象并放置在hashMap中
*
* 保证一个颜色对应的对象只有一个
*/
public class CircleFactory {
private static final HashMap<String,Shape> circleMap=new HashMap<>();
public static Shape getCircle(String color){
Circle circle= (Circle) circleMap.get(color);
if(circle==null){
circle=new Circle(color);
circleMap.put(color,circle);
System.out.println("Creating circle of color : " + color);
}
return circle;
}
}
package com.study.shejiPattern.share;
/**8
* 客户对象
* 用于生成对象
*/
public class Client {
private static final String colors[] =
{ "Red", "Green", "Blue", "White", "Black" };
public static void main(String[] args) {
for(int i=0; i < 20; ++i) {
Circle circle =
(Circle)CircleFactory.getCircle(getRandomColor());
circle.setX(getRandomX());
circle.setY(getRandomY());
circle.setRadius(100);
circle.draw();
System.out.println(circle);
}
}
private static String getRandomColor() {
return colors[(int)(Math.random()*colors.length)];
}
private static int getRandomX() {
return (int)(Math.random()*100 );
}
private static int getRandomY() {
return (int)(Math.random()*100);
}
}
很明显可以看到生成的red的circle都是一个对象,但是属性还是不相同的。
(8)代理模式
SpringAOP的底层
概念:
生成一个对象的代理对象,用代理对象提供外界接口
意图:为其他对象提供一种代理以控制对这个对象的访问。
主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
如何解决:增加中间层。(代理层)
应用实例: 1、Windows 里面的快捷方式。2.spring aop。
使用场景:按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。
注意事项: 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
代码实现:
静态代理:
真实的类和代理的类都实现image接口,代理的类已经存在
package com.study.shejiPattern.proxy;
public interface Image {
void display();
}
package com.study.shejiPattern.proxy;
public class RealImage implements Image {
private String fileName;
public RealImage(String fileName){
this.fileName = fileName;
loadFromDisk(fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
private void loadFromDisk(String fileName){
System.out.println("Loading " + fileName);
}
}
package com.study.shejiPattern.proxy;
/**8
* 代理对象:RealImage的代理
* 如果没有RealImage对象就生成,如果有对象就直接调用之前的realImage对象
*/
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.study.shejiPattern.proxy;
/***
* 输出:
* Loading test_10mb.jpg
* Displaying test_10mb.jpg
*
* Displaying test_10mb.jpg
*
* 开始会生成loading的原因是:在生成对象时构造函数中调用
* 后面不会生成loading的原因是:已经有对象了直接调用对象中的display
*/
public class Client {
public static void main(String[] args) {
Image image = new ProxyImage("test_10mb.jpg");
// 图像将从磁盘加载
image.display();
System.out.println("");
// 图像不需要从磁盘加载
image.display();
}
}
动态代理:
代理类是自动生成的
一个动态代理类可以代理多个类 而一个静态代理类只能代理那一个类
动态代理分为两类:
-
基于接口实现:JDK动态代理
-
基于类的动态代理:cglib
主要是InvocationHandler这个接口和Proxy类
InvocationHandler接口是:调用处理程序并返回结果
Proxy类:生成代理类
package com.study.shejiPattern.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 会用这个类自动生成代理类
*/
public class ProxyInvocationHandler implements InvocationHandler{
//被代理对象接口
private Image image;
public void setImage(Image image) {
this.image = image;
}
//得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),image.getClass().getInterfaces(),this);
}
//处理代理实例 并得到结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(image, args);
return result;
}
}
ProxyInvocationHandler proxyInvocationHandler=new ProxyInvocationHandler();
Image image= (Image) proxyInvocationHandler.getProxy();