设计模式---结构型模式

从程序结构上实现松耦合,从而可以扩大整体的类结构

(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();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值