Java设计模式(装饰者模式-组合模式-外观模式-享元模式)

1.装饰者模式

1.1 装饰者模式概述

(1)基本介绍

①装饰者模式:动态的将新功能附加到对象上,在对象功能扩展方面,它
	比继承更有弹性,也体现出了开闭原则

(2)分析图
在这里插入图片描述
PS:java的IO结构FilterInputStream就是用的装饰者模式

1.2 代码理解

1.Drink类

package com.pattern.设计模式.装饰者模式;

public abstract class Drink {
    public String des;
    private Float price = 0.0F;

    public Drink() {
    }

    public Drink(String des, Float price) {
        this.des = des;
        this.price = price;
    }

    public String getDes() {
        return des;
    }

    public void setDes(String des) {
        this.des = des;
    }

    public Float getPrice() {
        return price;
    }

    public void setPrice(Float price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Drink{" +
                "des='" + des + '\'' +
                ", price=" + price +
                '}';
    }

    // 计算费用的方法
    // 定义成一个抽像方法,让子类去实现它
    public abstract float cost();
}

2.Decorator类

package com.pattern.设计模式.装饰者模式;

public class Decorator extends Drink{

    private Drink drink;

    public Decorator(Drink drink){
        this.drink = drink;
    }

    @Override
    public float cost() {
        // 这里拿到调料自己的价格 + 咖啡的价格
        return super.getPrice() + drink.cost();
    }

    @Override
    public String getDes() {
        // 拿到自己的信息 + 价格 再去拿到咖啡的信息
        return super.des + " " + super.getPrice() + "&&" + drink.getDes();
    }
}

3.Coffee类

package com.pattern.设计模式.装饰者模式;

public class Coffee extends Drink {
    @Override
    public float cost() {
        return super.getPrice();
    }
}

4.继承Coffee的子类,可以自行添加(这里就写一个例子)

package com.pattern.设计模式.装饰者模式;

public class ShortBlack extends Coffee{

    public ShortBlack(){
        setDes("shortBlack");
        setPrice(4.0F);

    }
}

5.继承Decorator的子类 同上

package com.pattern.设计模式.装饰者模式;

public class Soy extends Decorator{

    public Soy(Drink drink) {
        super(drink);
        setDes("豆浆");
        setPrice(2.0F);

    }
}

6.测试类(牛奶等等可自行添加)

package com.pattern.设计模式.装饰者模式;

public class Test {
    public static void main(String[] args) {
        // 下单2份牛奶 + 一份豆浆的ShortBlack

        // 1.点一份ShortBlack
        Drink drink = new ShortBlack();
        System.out.println(drink);

        // 加如一份豆浆
        drink = new Soy(drink);
        System.out.println(drink);
        System.out.println(drink.cost());

        // 加入一份牛奶
        drink = new Milk(drink);
        System.out.println(drink);
        System.out.println(drink.cost());

        // 再加一份牛奶
        drink = new Milk(drink);
        System.out.println(drink);
        System.out.println(drink.cost());
    }
}

2.组合模式

2.1 组合模式概述

(1)基本介绍

	①它又称部分整体模式,他创建了对象组的树形结构,将对象组合成
		树状结构以表示 整体-部分 的层次关系

	②组合模式依据树形结构来组合对象,用来表示部分以及整体的层次

	③属于结构性设计模式

	④组合模式使得用户对单个对象和组合对象得访问具有一致性,即:
		组合能让客户以一致性的方式处理个别对象以及组合对象

(2)类图理解
在这里插入图片描述
PS:组合模式在JDK的HashMap中使用到了

(3)组合模式的注意事项和细节

1.简化客户端操作,客户端只需要面对一致的对象而不用考虑整体部分
	或者节点叶子的问题

2.具有较强的扩展性,当我们需要该组合对象时,我们只需要调整内部的
	层次关系,	客户端不需要做出任何改动

3.方便创建出复杂的层次结构,客户端不用理会组合里面的组成细节, 
	容易添加节点或者叶子从而创建出复杂的树形结构

4.需要遍历组织机构,或者处理的对象具有树形结构时,非常适合
	使用组合模式

5.要求较高的抽象性,如果节点和叶子有很多差异性的话,不适合
	使用组合模式

2.2 代码理解

1.OrganizationComponent类

package com.pattern.设计模式.组合模式;

public abstract class Component {

    private String name;
    private String des;



    protected void add(Component component){
        // 默认实现

    }

    protected void remove(Component component){

    }

    // 抽象方法 继承的子类都需要实现
    protected abstract void print();

    // 构造器
    public Component(){

    }

    public Component(String name, String des) {
        super();
        this.name = name;
        this.des = des;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDes() {
        return des;
    }

    public void setDes(String des) {
        this.des = des;
    }

    @Override
    public String toString() {
        return "Component{" +
                "name='" + name + '\'' +
                ", des='" + des + '\'' +
                '}';
    }
}

2.Department类

package com.pattern.设计模式.组合模式;

public class Department extends Component{

    public Department() {
    }

    public Department(String name, String des) {
        super(name, des);
    }

    @Override
    public String getName() {
        return super.getName();
    }

    @Override
    public String getDes() {
        return super.getDes();
    }

    @Override
    protected void print() {
        System.out.println("<><><>" + getName() + "<><><>");
    }
}

3.College类

package com.pattern.设计模式.组合模式;

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

public class College extends Component{

    List<Component> list = new ArrayList<Component>();

    public College() {
    }

    public College(String name, String des) {
        super(name, des);
    }

    @Override
    protected void add(Component component) {
        list.add(component);
    }

    @Override
    protected void remove(Component component) {
        list.remove(component);
    }

    @Override
    public String getName() {
        return super.getName();
    }

    @Override
    public String getDes() {
        return super.getDes();
    }

    @Override
    protected void print() {
        System.out.println("<<>>" + getName() + "<><>");
        for (Component component : list) {
            component.print();

        }
    }
}

4.University类

package com.pattern.设计模式.组合模式;

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

public class University extends Component{

    List<Component> list = new ArrayList<Component>();

    public University() {
    }

    // 构造器
    public University(String name, String des) {
        super(name, des);
    }

    // 重写add方法

    @Override
    protected void add(Component component) {
        list.add(component);
    }

    @Override
    protected void remove(Component component) {
        list.remove(component);
    }

    @Override
    public String getName() {
        return super.getName();
    }

    @Override
    public String getDes() {
        return super.getDes();
    }



    @Override
    protected void print() {
        System.out.println(">>>>" + getName() + "<<<<<");

        for (Component component : list) {
            component.print();
        }
    }
}

5.测试类

package com.pattern.设计模式.组合模式;

public class Test {
    public static void main(String[] args) {
        // 从大到小创建对象

        // 创建大学
        Component university = new University("北大", "China");

        // 创建学院
        Component component = new College("计算机学院", "软件工程");
        Component component1 = new College("天文学学院", "看星星");

        // 创建计算机学院的系
        component.add(new Department("软件工程", "敲代码"));
        component.add(new Department("计算机应用", "边敲代码边焊电"));
        component.add(new Department("网络工程", "网络工程"));

        // 创建天文学学院的系
        component1.add(new Department("天文学", "看不完的星星"));

        // 将学院加入到 学校
        university.add(component);
        university.add(component1);

        university.print();
    }
}

3.外观模式

3.1 外观模式概述

(1)基本介绍

①外观模式也叫过程模式,外观模式为子系统中的一组接口提供一个
	一致的界面。此模式定义了一个高级接口,这个接口使得这一子
	系统更加容易使用

②外观模式通过定义一个一致的接口,用已屏蔽内部子系统的细节,
	使得调用端跟这个接口发生调用,则无需关心这个子系统的内部细节

(2)原理类图
在这里插入图片描述
(3)Mybatis中的Configuration去创建MetaObject对象使用到了外观模式

(4)外观模式的注意事项和细节

1.外观模式对外屏蔽了子系统的细节,因此降低了客户端对子系统
	使用的复杂性

2.外观模式客户端与子系统的耦合关系,让子系统内部的模块更易于
	维护和扩展

3.通过合理的使用外观模式,可以帮我们更好的划分访问层次

4.当系统需要进行分层设计时,可以考虑使用外观模式

5.在维护一个遗留的大型系统时,可能这个系统已经变得难以维护和
	扩展,此时可以考虑为新系统开发一个外观类,来提供遗留系统的
	比较清晰简单的接口,让系统与外观类交互,提高复用性

6.不能过多的或者不合理的使用外观模式,使用外观模式好,还是
	直接调用模块好,要以让系统有层次,利于维护为目的。

3.2 代码理解

1.子系统类例子代码(自行增加即可)

package com.pattern.设计模式.外观模式;

public class DVDPlayer {

    // 使用单例模式 恶汉式
    private static DVDPlayer dvdPlayer = new DVDPlayer();

    public static DVDPlayer getInstance(){
        return dvdPlayer;
    }

    // 打开功能
    public void open(){
        System.out.println("DVD打开了");
    }

    // 关闭
    public void close(){
        System.out.println("DVD关闭");
    }

    // 播放
    public void play(){
        System.out.println("DVD播放");
    }

    // 暂停
    public void stop(){
        System.out.println("DVD暂停");
    }
}

2.客户端类

package com.pattern.设计模式.外观模式;

public class HomeTheaterFaced {

    // 定义各个子系统
    private TheaterLight theaterLight;
    private Popcorn popcorn;
    private DVDPlayer dvdPlayer;
    private Screen screen;
    private Stereo stereo;
    private Projector projector;

    public HomeTheaterFaced() {
        this.theaterLight = TheaterLight.getInstance();
        this.popcorn = Popcorn.getInstance();
        this.dvdPlayer = DVDPlayer.getInstance();
        this.screen = Screen.getInstance();
        this.stereo = Stereo.getInstance();
        this.projector = Projector.getInstance();
    }

    public void getMake(){
        popcorn.open();
        popcorn.pop();
        screen.open();
        projector.open();
        stereo.open();
        dvdPlayer.open();
        theaterLight.open();
    }

    public void play(){
        dvdPlayer.play();
    }

    public void stop(){
        dvdPlayer.stop();
    }

    public void end(){
        popcorn.close();
        screen.close();
        projector.close();
        stereo.close();
        dvdPlayer.close();
        theaterLight.close();
    }


}

3.测试类

package com.pattern.设计模式.外观模式;

public class Test {
    public static void main(String[] args) {
        HomeTheaterFaced homeTheaterFaced = new HomeTheaterFaced();
        homeTheaterFaced.getMake();
        homeTheaterFaced.play();
        homeTheaterFaced.stop();
        homeTheaterFaced.end();
    }
}

4.享元模式

4.1 享元模式概述

(1)基本介绍

①享元(Flyweight)模式也叫蝇量模式,运用共享技术有效的支持大量
	细粒度的对象

②常用于系统底层开发,解决系统的性能问题,比如数据库连接池,
	里面都是创建好的连接对象,在这些连接对象中有我们需要的则
	直接拿来用,避免重新创建,如果我们需要,则创建一个

③享元模式能解决重复对象的内存浪费问题,当系统中有大量相似
	对象,需要缓冲池时,不需要总是创建对象,可以冲缓冲池拿,
	这样可以降低系统内存,同时提高效率

④享元模式经典的应用场景就是池技术,Stirng常量池,数据库
	连接池,缓冲池等等都是享元模式的应用,享元模式是池技术
	的重要实现方式

(2)介绍扩展–内部状态和外部状态

1.享元模式提出了两个要求,细粒度和共享对象,涉及到内部状态和
	外部状态,即:将对象的信息分为两个部分,内部状态和外部状态

2.内部状态:指对象共享出来的信息,存储在享元对象内部且不会随
	环境的改变而改变

3.外部状态:指对象得以依赖的一个标记,是随环境改变为改变的,
	不可共享的状态

(3)类图
在这里插入图片描述
(4)JDK中,Integer源码就是用到了享元模式

(5)享元模式注意事项和细节

1.享元模式可以这样理解:享就是共享,元就是对象

2.系统中有大量对象,这些对象消耗大量内存,并且对象的状态大部分
	可以外部化时,我们就可以考虑选用享元模式

3.用唯一标识码判断,如果内存中有,则返回这个唯一标识码所标识的
	对象,用HashMap / HashTable存储

4.享元模式大大减少了对象的创建,降低了程序内存占用,提高效率

5.享元模式提高了系统的复杂度,需要分离出内部状态和外部状态,
	而外部状态具有固化特性,不应该随着内部状态改变而改变,这
	是我们使用享元模式需要注意的地方

6.使用享元模式时,注意划分内部状态和外部状态,并且需要一个
	共产类加以控制

7.享元模式经典使用场景有:String常量池,数据库连接池

4.2 代码理解

1.WebSiteFactory类

package com.pattern.设计模式.享元模式;


import java.util.HashMap;

public class WebSiteFactory {

    // 集合 充当池的作用
    private HashMap<String, ConcreteWebSite> hashMap = new HashMap<>();

    // 根据网站的类型返回一个网站 如果没有就创建放入池中,并返回
    public WebSite getWebSite(String type){
        // 如果没有,就创建一个放入池中
        if (!hashMap.containsKey(type)){
            hashMap.put(type, new ConcreteWebSite(type));
        }
        return (WebSite) hashMap.get(type);

    }

    // 获取网站的分类总数
    public int getCount(){
        return hashMap.size();
    }
}

2.WebSite类

package com.pattern.设计模式.享元模式;

public abstract class WebSite {

    public abstract void use(User user);

}

3.ConcreteWebSite 类

package com.pattern.设计模式.享元模式;

public class ConcreteWebSite extends WebSite{
    private String type = "";  // 网站发布的类型

    public ConcreteWebSite(String type){
        this.type = type;
    }
    @Override
    public void use(User user) {
        System.out.println("网站的发布形式为:" + type + " " + user.getName() + "在使用它>>>");
    }
}

4.java实体类User

package com.pattern.设计模式.享元模式;

public class User {
    private String name;

    public User() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

5.测试类

package com.pattern.设计模式.享元模式;

public class Test {
    public static void main(String[] args) {
        // 创建一个工厂类
        WebSiteFactory webSiteFactory = new WebSiteFactory();

        // 客户需要一个以新闻形式发布的网站
        WebSite webSite = webSiteFactory.getWebSite("新闻");
        webSite.use(new User("李白"));

        // 以博客形式
        WebSite webSite1 = webSiteFactory.getWebSite("博客");
        webSite1.use(new User("杜甫"));

        // 再建一个以博客形式
        WebSite webSite2 = webSiteFactory.getWebSite("博客");
        webSite2.use(new User("李清照"));

        System.out.println("网站的分类共:" + webSiteFactory.getCount());
    }
}

5.代理模式

代理模式 等等

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值