23种设计模式-七种结构型模式

Interview / 2020-05-17

两类

类:继承接口和类
对象:组合或者聚合

代理模式(Proxy)

中介,不能直接访问对象,而是通过访问代理访问对象,在代理中可以对访问者进行限制,增加了对象的安全性

实现:

  • 主题接口
  • 主题实现
  • 代理

主题接口

package com.DesignPatterns.structureModel.proxyModel;

/**
 * @Author redarm
 * @Date 2020/5/17 8:29 下午
 * 代理模式
 **/
public interface Subject {

    void access();
}


主题实现

package com.DesignPatterns.structureModel.proxyModel;

/**
 * @Author redarm
 * @Date 2020/5/17 8:33 下午
 **/
public class RealSubject implements Subject {

    @Override
    public void access() {
        System.out.println("Access successfully");
    }
}

代理

package com.DesignPatterns.structureModel.proxyModel;

/**
 * @Author redarm
 * @Date 2020/5/17 8:35 下午
 **/
public class SubjectProxy implements Subject {

    private RealSubject realSubject = null;

    @Override
    public void access() {

        if (realSubject == null){
            realSubject = new RealSubject();
        }

        preAccess();
        realSubject.access();
        postAccess();

    }

    public void preAccess(){
        System.out.println("before access");
    }

    public void postAccess(){
        System.out.println("after access");
    }
}

class Main{

    public static void main(String[] args) {
        SubjectProxy proxy = new SubjectProxy();

        proxy.access();
    }
}

应用:

  • 远程代理:通过代理隐藏真实IP
  • 安全代理:控制访问权限
  • 延迟代理:延迟对对象的反问,增加性能

适配器模式(Adapter)

将一个类的接口转换成需要的另一个接口,起到适配的作用

实现

  • 目标接口
  • 适配者类
  • 适配器类

类:

将phone类适配成computer类,computer就是适配的目标,定义为接口,phone就是适配者,定义为类

package com.DesignPatterns.structureModel.adapter;

/**
 * @Author redarm
 * @Date 2020/5/18 11:21 上午
 * ClassAdapter Design Patterns
 **/
public class AdapterTest {

    public static void main(String[] args) {

        Computer computer = new PhoneComputerAdapter();

        computer.getName();
    }
}

interface Computer{
    void getName();
}

class Phone{

    void getPhoneName(){
        System.out.println("I am a Phone");
    }
}

class PhoneComputerAdapter extends Phone implements Computer{

    @Override
    public void getName() {
        getPhoneName();
    }
}

对象:

将苹果适配成橘子,橘子接口,苹果类

package com.DesignPatterns.structureModel.adapter;

/**
 * @Author redarm
 * @Date 2020/5/18 11:30 上午
 * ClassAdapter DesignPatterns
 **/
public class ObjectAdapter {

    public static void main(String[] args) {

        Orange orange = new AppleOrangeAdapter();

        orange.getName();
    }
}

interface Orange{
    void getName();
}

class Apple{
    void getName(){
        System.out.println("I am a Apple");
    }
}

class AppleOrangeAdapter implements Orange{

    private Apple apple;

    public AppleOrangeAdapter(){
        this.apple = new Apple();
    }

    @Override
    public void getName() {
        apple.getName();
    }
}

桥接模式(Bridge)

一个类有多个维度的属性,比如苹果有大小,颜色两个属性,并且每个属性有多个实现

实现:

  • 属性接口
  • 属性实现
  • 类实现

大小红绿苹果

package com.DesignPatterns.structureModel.bridge;

/**
 * @Author redarm
 * @Date 2020/5/18 11:50 上午
 * Birdge DesignPatterns
 **/
public class Bridge {

    public static void main(String[] args) {

        Apple bigRedApple = new Apple(new Red(), new BigSize());
        Apple smallGreenApple = new Apple(new Green(), new SmallSize());

        System.out.println("Big one: " + bigRedApple.toString() + "\nsmall one: " + smallGreenApple.toString());
    }
}

interface AppleSize{

    String showSize();
}

class BigSize implements AppleSize{

    @Override
    public String showSize() {
        return ("I am a Big Apple");
    }
}

class SmallSize implements AppleSize{

    @Override
    public String showSize() {
        return("I am a small Apple");
    }
}

interface AppleColor{

    String showColor();
}

class Red implements AppleColor{

    @Override
    public String showColor() {
        return("My color is red");
    }
}

class Green implements AppleColor{

    @Override
    public String showColor() {
        return("My color is green");
    }
}

class Apple{

    private AppleColor appleColor;

    private AppleSize appleSize;

    public Apple(AppleColor appleColor, AppleSize appleSize){
        this.appleColor = appleColor;
        this.appleSize = appleSize;
    }

    @Override
    public String toString() {
        return "My size: " + appleSize.showSize() + " , and my color is :" + appleColor.showColor();
    }
}

装饰模式(Decorator)

不改变现有对象类的情况下,给他加一些装饰

实现

package com.DesignPatterns.structureModel.decorator;

/**
 * @Author redarm
 * @Date 2020/5/18 3:06 下午
 * Decorator Design patterns
 **/
public class Decorator {

    public static void main(String[] args) {

        Apple apple = new AppleWithColorAndSize("Red","Big");

        System.out.println(apple.getInfo());
    }
}

interface Apple{

    String getInfo();
}

class AppleWithColor implements Apple{

    private String color;

    public AppleWithColor(String color){
        this.color = color;
    }

    @Override
    public String getInfo() {
        return "My color is " + this.color;
    }
}

class AppleWithColorChange implements Apple{

    protected Apple apple;

    public AppleWithColorChange(String color){
        this.apple = new AppleWithColor(color);
    }

    @Override
    public String getInfo() {
        return apple.getInfo();
    }
}

class AppleWithColorAndSize extends AppleWithColorChange{

    private String size;

    public AppleWithColorAndSize(String color, String size){
        super(color);
        this.size = size;
    }

    @Override
    public String getInfo() {
        return super.getInfo() + "\nmy size is " + this.size;
    }
}

外观模式(Facade)

多个子系统有同一个的对外类

实现

  • 外观类
  • 多个子系统类

一个部门类表示对外外观类,子系统为设计部门,开发部门,测试部门

package com.DesignPatterns.structureModel.facade;

/**
 * @Author redarm
 * @Date 2020/5/19 3:25 下午
 * Facade DesignPatterns
 **/
public class Facade {

    public static void main(String[] args) {
        Departments departments = new Departments();
        departments.outputDepartments();
    }
}

class Departments{

    private DesignDepartment designDepartment = new DesignDepartment();
    private DevelopmentDepartment developmentDepartment = new DevelopmentDepartment();
    private TestDepartment testDepartment = new TestDepartment();

    public void outputDepartments(){
        System.out.println(designDepartment.show() + "\n" + developmentDepartment.show() + "\n"
                                + testDepartment.show());
    }
}

class DesignDepartment{

    String show(){
        return "I am design department";
    }
}

class DevelopmentDepartment{

    String show(){
        return "I am development department";
    }
}

class TestDepartment{

    String show(){
        return "I am test department";
    }
}

享元模式(Flyweight)

大量的相同的需要复用的对象,比如五子棋棋子,桌子,椅子,为了避免大量新建对象,相同的对象只有一份

实现

  • 抽象享元对象
  • 多个享元对象的实现
  • 享元工厂:每个不同的对象存一份,提供得到每个对象的方法

享元桌子,多个实现,提供一个工厂,每个类型存一份,如果使用就从中取出

package com.DesignPatterns.structureModel.flyweight;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author redarm
 * @Date 2020/5/19 3:56 下午
 * Flyweight DesignPatterns
 **/
public class Flyweight {

    public static void main(String[] args) {
        Tables tables = new Tables();
        tables.getOne("red").show();
        tables.getOne("big").show();
        tables.getOne("redarm");
    }
}

class Tables{

    private List<Table> tables = new ArrayList<>();

    public Tables(){
        tables.add(new BigTable());
        tables.add(new SmallTable());
        tables.add(new BlackTable());
        tables.add(new RedTable());
    }

    public Table getOne(String type){
        switch (type){

            case "big": return tables.get(0);
            case "small": return tables.get(1);
            case "black": return tables.get(2);
            case "red": return tables.get(3);

            default:
                System.out.println("do not have this type");
                return null;
        }

    }
}

interface Table{

    void show();
}

class BigTable implements Table{

    @Override
    public void show() {
        System.out.println("I am a big table");
    }
}

class SmallTable implements Table{

    @Override
    public void show() {
        System.out.println("I am a small table");
    }
}

class RedTable implements Table{

    @Override
    public void show() {
        System.out.println("I am a red table");
    }
}

class BlackTable implements Table{

    @Override
    public void show() {
        System.out.println("I am a black table");
    }
}


应用:

  • 大量相同对象,如果每个对象都存一份浪费内存
  • 由于需要维护一个存储享元的数据结构,所以重复的对象足够多的时候使用的意义大一点

组合模式(Composite)

多个部分组成一个整体,并且多个整体又可以组成一个新的整体,以此类推构成树形结构:每个部分为一个树叶,整体为树枝,树枝和树叶实现同一个接口,所以树枝和树叶可以同等对待

实现

  • 组成部分接口
  • 树叶,实现组成部分接口
  • 树枝,实现组成部分接口:存储树叶,提供增加删除方法

两种实现方式:

  • 透明方式:存储和删除方法由组成部分声明,所有树叶和树枝都要实现方法,好处是树叶和树枝同等对待,方法跟组成部分一样,同等对待,缺点是树叶不需要增加删除方法,只能返回空
  • 安全方式:存储和删除方法只在树枝中声明实现,优点是树叶部分不再需要实现无用的方法,缺点是树枝在组成部分的接口上多实现了方法,所以不能跟树叶同等对待

透明方式,SDUT有两个部门和一个子公司,这个子公司有两个部门

package com.DesignPatterns.structureModel.composite;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author redarm
 * @Date 2020/5/19 4:47 下午
 * Composite DesignPatterns
 **/
public class Composite {

    public static void main(String[] args) {

        Component A = new Subsidiary("SDUT company");
        A.add(new Department("a department"));
        A.add(new Department("b department"));
        Subsidiary C = new Subsidiary("C company");
        A.add(C);

        C.add(new Department("d department"));
        C.add(new Department("e department"));

        A.show();

    }
}

interface Component{

    void show();

    void remove(Component component);

    void add(Component component);
}

class Department implements Component{

    private String name;

    public Department(String name){
        this.name = name;
    }

    @Override
    public void show() {
        System.out.println("a department and name is " + this.name);
    }

    @Override
    public void remove(Component component) {

    }

    @Override
    public void add(Component component) {

    }
}

class Subsidiary implements Component{

    private List<Component> components = new ArrayList<>();

    private String name;

    public Subsidiary(String name){
        this.name = name;
    }

    @Override
    public void show() {
        System.out.println("Company name is " + this.name);
        System.out.println("Company has " + components.size() + " departments or subsidiary, and they are :");
        for (Component component : components){
            component.show();
        }
    }

    @Override
    public void remove(Component component) {
        components.remove(component);
    }

    @Override
    public void add(Component component) {
        components.add(component);
    }
}

应用:
部门和子公司:一个公司有多个部门和子公司,每个子公司也有多个部门和子公司
文件和文件夹:文件夹里有多个文件和文件夹,每个文件夹中又有多个文件和文件夹