2021-10-18

一、策略设计模式(strategy)
(1)概念:

oop(面向对象)模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用 算法的客户。

00p原则:封装变化 多用组合,少用继承 针 对 接 口 编 程 , 不 针 对实现编程。

将变化的部分抽取出来重新封装成接口,在通过组合的方式实现代码复用和扩展。

(2)案例:
package DesignPattern.strategy.gameExample;

//角色类,角色可以动态切换各种武器,所以将变化的武器抽离出来封装成接口,然后通过组合组装到角色类中
public abstract class GameRole {
    private Weapon weapon;

    public GameRole() {
        this.weapon = new FistWeapon();
    }

    public abstract void initEquipment();

    public void useWeapon(){
         weapon.useMode();
    }

    public void sayPrologue(){
        System.out.println("解救公主还是得靠我!!");
    }

    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }
}
package DesignPattern.strategy.gameExample;

//普通角色
public class SimpleGameRole extends  GameRole {
     @Override
     public void initEquipment(){
         System.out.println("白衬衫");
     }
}
package DesignPattern.strategy.gameExample;

public interface Weapon {
    void useMode();
}
//武器实现类
package DesignPattern.strategy.gameExample;

public class FistWeapon implements Weapon {
    @Override
    public void useMode() {
        System.out.println("向前猛击!");
    }
}

package DesignPattern.strategy.gameExample;

public class KnifeWeapon implements Weapon {
    @Override
    public void useMode() {
        System.out.println("向前刺!");
    }
}

package DesignPattern.strategy.gameExample;

public class GunWeapon implements Weapon {
    @Override
    public void useMode() {
        System.out.println("向前开枪!");
    }

}

package DesignPattern.strategy.gameExample;
//测试
public class Test {
    public static void main(String[] args) {
        GameRole gameRole = new SimpleGameRole();
        gameRole.initEquipment();
        gameRole.useWeapon();
        //切换不同的武器
        gameRole.setWeapon(new GunWeapon());
        gameRole.useWeapon();
    }
}


(3)项目中的实际应用
package com.xyzq.service.ylbConfig.outsideConfig.strategy;

import java.util.Map;

//将变化的release()算法方法抽出来封装成接口,作为一个算法族
public interface ReleaseArithmetic {
    String release(Map<String,Object> paramMap);
}

package com.xyzq.service.ylbConfig.outsideConfig.strategy;

import com.alibaba.fastjson.JSONObject;
import com.xyzq.core.util.DateUtils;
import com.xyzq.dao.mysqlds1.ylbmultiversion.YLBVersionInfoDao;
import com.xyzq.entity.mysqlds1.appconfig.ItemChangeSets;
import com.xyzq.entity.mysqlds1.ylbmultiversion.YLBVersionInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class RookieGiftReleaseArithmetic implements ReleaseArithmetic {

    @Autowired
    private YLBVersionInfoDao ylbConfigVersionInfoDao;

    @Autowired
    private DefaultReleaseArithmetic defaultReleaseArithmetic;

    @Override
    public String release(Map<String, Object> para) {
        Map<String, Object> version_params = new HashMap<>();
        version_params.put("version_no", 60000);//6.0版本以上更新就好
        List<YLBVersionInfo> versionList = ylbConfigVersionInfoDao.findAll(version_params);
        String resultStr = null;
        for(YLBVersionInfo version:versionList){
            Map<String, Object> params = new HashMap<>();
            //生成appconfig
            params.put("app_id", "ulb");
            params.put("version_id", version.getVersion_id());
            params.put("module_id", para.get("module_id"));
            params.put("config_key", para.get("config_key"));
            params.put("version_name", version.getVersion_name());
            params.put("version_no", version.getVersion_no());
            params.put("release_name", DateUtils.getCurrentDate() + "我的配置更新");
            params.put("releaseComment", "我的配置更新");

            params.put("operator", para.get("operator"));
            params.put("config_value", para.get("value"));

            //步骤1:更新configItem表
            ItemChangeSets itemChangeSets = defaultReleaseArithmetic.updateItem(params);

            //步骤2:取release表的configuration,仅更新该值;同时更新allconfig
            if(itemChangeSets != null){} //后期加
            params.put("changes",itemChangeSets);
            String configuration = defaultReleaseArithmetic.getHistoryConfiguration(params);
            JSONObject configulationJsonObject = new JSONObject();
            if(configuration != null){
                configulationJsonObject = JSONObject.parseObject(configuration);
                //设置改变的值,需格式化校验
                configulationJsonObject.put(para.get("config_key").toString(), defaultReleaseArithmetic.valueCheck(para.get("value")));
            }else{
                configulationJsonObject.put(para.get("config_key").toString(), defaultReleaseArithmetic.valueCheck(para.get("value")));
            }
            params.put("configuration", configulationJsonObject.toJSONString());
            resultStr = defaultReleaseArithmetic.updateRelease(params);
        }
        return resultStr;
    }
}

package com.xyzq.service.ylbConfig.outsideConfig.strategy;

import com.xyzq.dao.mysqlds1.ylb6.mine.YlbSelfConfigDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class SelfInterfaceReleaseArithmetic implements ReleaseArithmetic {

    @Autowired
    private YlbSelfConfigDao ylbSelfConfigDao;

    @Override
    public String release(Map<String, Object> para) {
        //删除之前上架的数据
        String column_id = (String)para.get("column_id");
        ylbSelfConfigDao.releaseDelete(column_id);
        //将草稿中待上架数据上架
        para.put("status","1");
        ylbSelfConfigDao.selfReleaseDetail(para);
        return "执行成功!";
    }
}

package com.xyzq.service.ylbConfig.outsideConfig.strategy;

import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class ReleaseArithmeticInvoke{
    private ReleaseArithmetic releaseArithmetic;

    
    //动态的设置行为
    public void setReleaseArithmetic(ReleaseArithmetic releaseArithmetic) {
        this.releaseArithmetic = releaseArithmetic;
    }

    public void  invoke(Map<String,Object> map){
        releaseArithmetic.release(map);
    }
}


public String ylbRookieGiftAudit(YlbRookieGiftService ylbRookieGiftService,String status,String id) throws Exception {
        //status 0.审核不通过 1.提交审核 2.上架 3.下架
        String checkV1 = "0";
        String checkV2 = "1";
        String checkV3 = "2";
        String checkV4 = "3";
        //发布方式,根据传入的方法执行不同的发布逻辑
        String method = "rookieGiftRelease";
        String backStr = null;
        Map<String,Object> paraMap = new HashMap<>();
        paraMap.put("status",status);
        paraMap.put("id",id);
        Map<String, Object> para = new HashMap<>();
        para.put("module_id", "appconfig");
        para.put("config_key", "openAccountGuidance");
        para.put("operator", SecurityUtil.getCurrentStaff().getName());
        try {
            if (checkV1.equals(status)) {
                ylbRookieGiftDao.ylbRookieGiftChangeStatus(paraMap);
                backStr = "审核不通过操作成功!";
            } else if (checkV2.equals(status)) {
                ylbRookieGiftDao.ylbRookieGiftChangeStatus(paraMap);
                backStr = "提交审核操作成功!";
            } else if (checkV3.equals(status)) {
                //检查是否已有上架细信息
                int size = ylbRookieGiftDao.ylbRookieGiftAuditSize();
                if (size < 1) {
                    String value = ylbRookieGiftService.getConfigValue(id);
                    para.put("value", value);
                    // 策略模式应用,根据需求,放入不同的算法类
                    releaseArithmeticInvoke.setReleaseArithmetic(rookieGiftReleaseArithmetic);
                    releaseArithmeticInvoke.invoke(para);
                    
                    ylbRookieGiftDao.ylbRookieGiftChangeStatus(paraMap);
                    backStr = "上架成功!";
                } else {
                    backStr = "已有上架信息,请先下架之前新手礼包配置!";
                }
            } else if (checkV4.equals(status)) {
                String value = JSON.toJSONString(new HashMap<>());
                para.put("value", value);
                paraMap.put("status","0");
                
                // 策略模式应用,根据需求,放入不同的算法类
                releaseArithmeticInvoke.setReleaseArithmetic(rookieGiftReleaseArithmetic);
                releaseArithmeticInvoke.invoke(para);
                  
                ylbRookieGiftDao.ylbRookieGiftChangeStatus(paraMap);
                backStr = "下架成功!";
            }
        }catch (Exception e){
            e.printStackTrace();
            backStr = "操作失败!";
        }
        return backStr;
    }

(4)优化:

由于策略模式当算法类太多时,显得比较臃肿,无法直观的查看所有的业务。

所以我们可以通过 lamdba函数式接口和map来简化策略模式。

优化上面项目中用的策略模式

package com.xyzq.service.ylbConfig.outsideConfig.newDesign;

//lambda 函数式接口
@FunctionalInterface
public interface GeneralRelease<T> {
    void release(T t);
}

//发布分发接口
public interface ReleaseInvoke {
     void invoke(String method, Map<String,Object> map) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException;
}

package com.xyzq.service.ylbConfig.outsideConfig.newDesign;

import com.alibaba.fastjson.JSONObject;
import com.xyzq.core.util.DateUtils;
import com.xyzq.dao.mysqlds1.ylb6.mine.YlbSelfConfigDao;
import com.xyzq.dao.mysqlds1.ylbmultiversion.YLBVersionInfoDao;
import com.xyzq.entity.mysqlds1.appconfig.ItemChangeSets;
import com.xyzq.entity.mysqlds1.ylbmultiversion.YLBVersionInfo;
import com.xyzq.service.ylbConfig.outsideConfig.strategy.DefaultReleaseArithmetic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 发布业务方法类
 */
@Component
public class ConfigPublishService {

    @Autowired
    private YLBVersionInfoDao ylbConfigVersionInfoDao;

    @Autowired
    private YlbSelfConfigDao ylbSelfConfigDao;

    @Autowired
    private DefaultReleaseArithmetic defaultReleaseArithmetic;
    /**
     * 新手礼包发布方法
     * @param para
     * @return
     * @throws Exception
     */
    public String rookieGiftRelease(Map<String, Object> para)  {
        Map<String, Object> version_params = new HashMap<>();
        version_params.put("version_no", 60000);//6.0版本以上更新就好
        List<YLBVersionInfo> versionList = ylbConfigVersionInfoDao.findAll(version_params);
        String resultStr = null;
        for(YLBVersionInfo version:versionList){
            Map<String, Object> params = new HashMap<>();
            //生成appconfig
            params.put("app_id", "ulb");
            params.put("version_id", version.getVersion_id());
            params.put("module_id", para.get("module_id"));
            params.put("config_key", para.get("config_key"));
            params.put("version_name", version.getVersion_name());
            params.put("version_no", version.getVersion_no());
            params.put("release_name", DateUtils.getCurrentDate() + "我的配置更新");
            params.put("releaseComment", "我的配置更新");

            params.put("operator", para.get("operator"));
            params.put("config_value", para.get("value"));

            //步骤1:更新configItem表
            ItemChangeSets itemChangeSets = defaultReleaseArithmetic.updateItem(params);

            //步骤2:取release表的configuration,仅更新该值;同时更新allconfig
            if(itemChangeSets != null){} //后期加
            params.put("changes",itemChangeSets);
            String configuration = defaultReleaseArithmetic.getHistoryConfiguration(params);
            JSONObject configulationJsonObject = new JSONObject();
            if(configuration != null){
                configulationJsonObject = JSONObject.parseObject(configuration);
                //设置改变的值,需格式化校验
                configulationJsonObject.put(para.get("config_key").toString(), defaultReleaseArithmetic.valueCheck(para.get("value")));
            }else{
                configulationJsonObject.put(para.get("config_key").toString(), defaultReleaseArithmetic.valueCheck(para.get("value")));
            }
            params.put("configuration", configulationJsonObject.toJSONString());
            resultStr = defaultReleaseArithmetic.updateRelease(params);
        }
        return resultStr;
    }

    public void selfInterfaceRelease(Map<String, Object> para){
        //删除之前上架的数据
        String column_id = (String)para.get("column_id");
        ylbSelfConfigDao.releaseDelete(column_id);
        //将草稿中待上架数据上架
        para.put("status","1");
        ylbSelfConfigDao.selfReleaseDetail(para);
    }

}

package com.xyzq.service.ylbConfig.outsideConfig.newDesign;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

// 发布类
@Component
public class DefaultReleaseInvoke implements ReleaseInvoke {
    Map<String,GeneralRelease<Map<String,Object>>> releaseMap = new HashMap<>();

    @Autowired
    private ConfigPublishService configPublishService;
    @Override
    public void invoke(String method,Map<String,Object> map) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        if(releaseMap.containsKey(method)){
            GeneralRelease<Map<String,Object>> generalRelease = releaseMap.get(method);
            if(generalRelease != null){
                generalRelease.release(map);
            }
        }
    }

    @PostConstruct
    public void initReleaseFunction(){
        releaseMap.put("rookieGiftRelease",map -> {
           configPublishService.rookieGiftRelease(map);
        });
    }
}


二、观察者模式(Observer)
(1)概念:

让你的对象知悉现况。观察者模式定义了对象之间的一对多依赖,这 样一来,当一个对象改变状态时,它的所有依赖者都 会收到通知并自动更新。观察者模式提供了一种对象设计,让主题和观察者之间松耦合。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u19FHiKh-1634514353576)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210520140140812.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PFLvmCC8-1634514353608)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210520140616166.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EVFNcMYy-1634514353610)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210520140638521.png)]

(2)案例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fu04x6eI-1634514353612)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210520161238165.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5E9f8ctb-1634514353614)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210520161334460.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aj7AIIw6-1634514353615)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210520161357148.png)]

用观察者模式实现一个简单的气象站

package DesignPattern.observer;

/**
 * 天气检测数据
 */

//可观察者
public interface Subject {
    void registerObserver(Observer weatherObserver);
    void removeObserver(Observer weatherObserver);
    void notifyObservers();
}
package DesignPattern.observer;

//观察者接口
public interface Observer {
    void update(float temperature,float humidity,float pressure);
}
package DesignPattern.observer;

//布告板接口
public interface BillboardElement {
    void display();
}

package DesignPattern.observer;

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

//可观察者实现
public class WeatherData implements Subject {
    private List<Observer> observers;
    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData() {
        this.observers = new ArrayList<>();
    }

    @Override
    public void registerObserver(Observer weatherObserver) {
        observers.add(weatherObserver);
    }

    @Override
    public void removeObserver(Observer weatherObserver) {
        observers.remove(observers.get(
                observers.indexOf(weatherObserver)));
    }

    @Override
    public void notifyObservers() {
        observers.stream().forEach(observer -> {
            observer.update(temperature,humidity,pressure);
        });
    }

   

    public void measurementChanged(){
        notifyObservers();
    }

    public void setData(float temperature,float humidity,float pressure){
        this.temperature =  temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementChanged();
    }
}


package DesignPattern.observer;

//观察者
public class WeatherCountBillboard implements Observer,BillboardElement{
    private float temperature;
    private float humidty;
    private Subject subject;

    public WeatherCountBillboard(Subject subject) {
        this.subject = subject;
        subject.registerObserver(this);
    }

    @Override
    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidty = humidity;
        display();
    }

    @Override
    public void display() {
        System.out.println("温度和湿度:"+temperature + "   || "+humidty);
    }
}
package DesignPattern.observer;

//观察者
public class WeatherCurrentStateBillboard implements Observer,BillboardElement {
    private float temperature;
    private float humidty;
    private float pressure;
    private Subject subject;

    public WeatherCurrentStateBillboard(Subject subject) {
        this.subject = subject;
        subject.registerObserver(this);
    }

    @Override
    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidty = humidity;
        this.pressure = pressure;
        display();
    }

    @Override
    public void display() {
        System.out.println("当前温度:"+temperature+"  || 当前湿度:"+humidty+"  || 当前压强:"+pressure);
    }
}
package DesignPattern.observer;

//观察者
public class WeatherPredictionBillboard implements Observer,BillboardElement {
    private float temperature;
    private float humidity;
    private float pressure;
    private Subject subject;

    public WeatherPredictionBillboard(Subject subject) {
        this.subject = subject;
        subject.registerObserver(this);
    }

    @Override
    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        display();
    }

    @Override
    public void display() {
        System.out.println("明天预计气温:"+temperature+"||  预计湿度:"+humidity+"  ||预计压强:"+pressure);
    }
}

package DesignPattern.observer;

public class Test {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        WeatherCountBillboard weatherCountBillboard = new WeatherCountBillboard(weatherData);
        WeatherCurrentStateBillboard weatherCurrentStateBillboard = new WeatherCurrentStateBillboard(weatherData);
        WeatherPredictionBillboard weatherPredictionBillboard = new WeatherPredictionBillboard(weatherData);
        weatherData.setData(25.0f,38.5f,29.7f);
        weatherData.setData(28.5f,30.6f,32.3f);
        weatherData.setData(32.8f,27.2f,38.6f);
    }
}

(3)spring项目中的实际应用-- spring事件驱动用的就是观察者模式

ApplicationEvent接口:所有的spring事件都是扩展ApplicationEvent接口,相当于可观察者。

ApplicationListener接口:基于标准的观察者模式的观察者接口。

ApplicationContext:事件源。

AbstractApplicationContext: spring容器实现类.

ApplicationEventPublisher: spring容器事件发布类。

ApplicationEventMulticaster: spring容器事件广播类

ApplicationEventPublisherAware:事件发布类

public abstract class ApplicationEvent extends EventObject {

	/** use serialVersionUID from Spring 1.2 for interoperability. */
	private static final long serialVersionUID = 7099057708183571937L;

	/** System time when the event happened. */
	private final long timestamp;


	/**
	 * Create a new ApplicationEvent.
	 * @param source the object on which the event initially occurred (never {@code null})
	 */
	public ApplicationEvent(Object source) {
		super(source);
		this.timestamp = System.currentTimeMillis();
	}


	/**
	 * Return the system time in milliseconds when the event happened.
	 */
	public final long getTimestamp() {
		return this.timestamp;
	}

}


@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}

@FunctionalInterface
public interface ApplicationEventPublisher {

	
	default void publishEvent(ApplicationEvent event) {
		publishEvent((Object) event);
	}

	
	void publishEvent(Object event);

}

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
    /** Helper class used in event publishing. */
	@Nullable
	private ApplicationEventMulticaster applicationEventMulticaster;

	/** Statically specified listeners. */
	private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();

	/** Local listeners registered before refresh. */
	@Nullable
	private Set<ApplicationListener<?>> earlyApplicationListeners;

	/** ApplicationEvents published before the multicaster setup. */
	@Nullable
	private Set<ApplicationEvent> earlyApplicationEvents;
    //初始化事件传播器
	initApplicationEventMulticaster();
    //注册事件监听器
	registerListeners();
    
    
    protected void finishRefresh() {
		// Clear context-level resource caches (such as ASM metadata from scanning).
		clearResourceCaches();

		// Initialize lifecycle processor for this context.
		initLifecycleProcessor();

		// Propagate refresh to lifecycle processor first.
		getLifecycleProcessor().onRefresh();

		// Publish the final event.
        //发布容器刷新事件
		publishEvent(new ContextRefreshedEvent(this));

		// Participate in LiveBeansView MBean, if active.
		LiveBeansView.registerApplicationContext(this);
	}
}


(4)自定义使用sping事件机制
package DesignPattern.observer.springObserver;

import org.springframework.context.ApplicationEvent;

//定义自定义事件
public class MyEvent extends ApplicationEvent {
    public MyEvent(Object source) {
        super(source);
        System.out.println("This is MyEvent");
    }

    public void println(){
        System.out.println("执行自定义事件的算法了");
    }
}

package DesignPattern.observer.springObserver;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

//定义自己的监听
@Component
public class MyListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        if(applicationEvent instanceof MyEvent){
            MyEvent myEvent = (MyEvent) applicationEvent;
            myEvent.println();
        }
    }
}

package DesignPattern.observer.springObserver;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;

package DesignPattern.observer.springObserver;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

//测试
public class Test {

    public static void main(String[] args) {
        ApplicationContext applicationContext =
                new AnnotationConfigApplicationContext("DesignPattern.observer.springObserver");
                /*MyEvent myEvent = (MyEvent) applicationContext.getBean("MyEvent");*/
                applicationContext.publishEvent(new MyEvent("1"));

    }
}

三、装饰者模式
(1)概念:

装饰者模式动态地将责任附加到对象上。 若要扩展功能,装饰者提供了比继承更有弹性的替代方案。装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。**被装饰者可以是一个抽象类也可以是接口,装饰着是继承了被装饰者的类型,而不是行为。行为是通过装饰者组合起来的新行为,可以动态改变被装饰者的行为。**缺点就是会产生很多小的类。

咖啡店例子:咖啡店里有饮料,饮料有各种类型,饮料里也可以加各种调料,还可以控制饮料的大小。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NK4xZxMC-1634514353617)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210521112203709.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o601nrpj-1634514353618)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210521112242917.png)]

(2)案例:
package DesignPattern.decoration;

//饮料抽象接口
public interface  Beverages {
     float cost();
     String  decription();
}
package DesignPattern.decoration;

//调料接口
public interface CondimentDecoration extends Beverages {
    @Override
    float cost();

    @Override
    String decription();
}
package DesignPattern.decoration;

//具体饮料类
public class Synthesize implements Beverages {
    @Override
    public float cost() {
        return 15.0f;
    }

    @Override
    public String decription() {
        return "综合";
    }
}
package DesignPattern.decoration;
//具体饮料类
public class DeepRoasting implements Beverages {
    @Override
    public float cost() {
        return 20.5f;
    }

    @Override
    public String decription() {
        return "深焙";
    }
}
package DesignPattern.decoration;
//具体饮料类
public class Espresso implements Beverages {
    @Override
    public float cost() {
        return 26.0f;
    }

    @Override
    public String decription() {
        return "浓缩";
    }
}
package DesignPattern.decoration;
//具体饮料类
public class HouseBlend implements Beverages {
    @Override
    public float cost() {
        return 21.5f;
    }

    @Override
    public String decription() {
        return "低咖啡因";
    }
}
package DesignPattern.decoration;

//具体调料类
public class MilkCondiment implements CondimentDecoration {
    private Beverages beverages;

    public MilkCondiment(Beverages beverages) {
        this.beverages = beverages;
    }

    @Override
    public float cost() {
        return 2+beverages.cost();
    }

    @Override
    public String decription() {
        return beverages.decription()+"牛奶";
    }
}
package DesignPattern.decoration;
//具体调料类
public class MilkFoamCondiment implements CondimentDecoration {
    private Beverages beverages;

    public MilkFoamCondiment(Beverages beverages) {
        this.beverages = beverages;
    }

    @Override
    public float cost() {
        return 5+beverages.cost();
    }

    @Override
    public String decription() {
        return beverages.decription()+"奶泡";
    }
}
package DesignPattern.decoration;
//具体调料类
public class MochaCondiment implements CondimentDecoration {
    private Beverages beverages;

    public MochaCondiment(Beverages beverages) {
        this.beverages = beverages;
    }

    @Override
    public float cost() {
        return 3+beverages.cost();
    }

    @Override
    public String decription() {
        return beverages.decription()+"摩卡";
    }
}
package DesignPattern.decoration;
//具体调料类
public class SoybeanMilkCondiment implements CondimentDecoration{
    private Beverages beverages;

    public SoybeanMilkCondiment(Beverages beverages) {
        this.beverages = beverages;
    }

    @Override
    public float cost() {
        return 4+beverages.cost();
    }

    @Override
    public String decription() {
        return beverages.decription()+"豆浆";
    }
}
package DesignPattern.decoration;

public class Test {
    public static void main(String[] args) {
        Beverages beverages = new Espresso();
        //分别用牛奶,摩卡,豆浆,奶泡佐料类包装浓缩咖啡,最后算出总共的价钱
        beverages = new MilkCondiment(beverages);
        beverages = new MochaCondiment(beverages);
        beverages = new SoybeanMilkCondiment(beverages);
        beverages = new MilkFoamCondiment(beverages);
        System.out.println("你点的咖啡是:"+beverages.decription()+",总共是:"+beverages.cost()+"元");
    }
}

(3)项目实际应用:

比如java.io 的各种流,如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f2jgkpg2-1634514353619)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210521145059795.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9mBcKjCW-1634514353620)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210521145122234.png)]

四、工厂模式
(1)简单工厂(不是设计模式,而编程习惯)

下面通过简单工厂来实现披萨店里各种披萨的创建

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r7d1mP36-1634514353620)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210521165244308.png)]

通过组合的方式在运行时动态的改变行为,因为我们可以不同的接口实现。

package DesignPattern.factory.headFirstCase.simpleFactory;

public interface Pizza {
    String name();
    double pirce();
    double size();
    void make();
}
package DesignPattern.factory.headFirstCase.simpleFactory;

public class FruitPizza implements Pizza {
    @Override
    public String name() {
        return "水果披萨";
    }

    @Override
    public double pirce() {
        return 50.0f;
    }

    @Override
    public double size() {
        return 25.0f;
    }

    @Override
    public void make() {
        System.out.println("水果披萨制作完成");
    }
}
package DesignPattern.factory.headFirstCase.simpleFactory;

public class ChickenPizza implements Pizza {
    @Override
    public String name() {
        return "鸡肉披萨";
    }

    @Override
    public double pirce() {
        return 75.0f;
    }

    @Override
    public double size() {
        return 12.5f;
    }

    @Override
    public void make() {
        System.out.println("鸡肉披萨制作完成");
    }
}

package DesignPattern.factory.headFirstCase.simpleFactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * 这里不把createPizza()变成静态方法是因为变成静态方法就不能通过继承来扩展修改createPizza()方法
 */
public class SimpleFactory {
    public Object createPizza(Class<?> clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Constructor<?> constructor = clazz.getDeclaredConstructor();
        Object o= constructor.newInstance();
        return o;
    }
}

package DesignPattern.factory.headFirstCase.simpleFactory;

import java.lang.reflect.InvocationTargetException;
//通过组合工厂对象和pizza,pizza商店可以动态的创建各种披萨,同时工厂可以同时被不同的pizza商店组合,扩展性高
public abstract class PizzaStore {
    private Pizza pizza;
    private SimpleFactory simpleFactory;


    public PizzaStore(SimpleFactory simpleFactory) {
        this.simpleFactory = simpleFactory;
    }

    public void orderPizza(Class<?> clazz){
        try {
            pizza = (Pizza) simpleFactory.createPizza(clazz);
            pizza.make();
        }catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException n){
            n.printStackTrace();
        }
    }
}



简单工厂就是将创建对象的变化给抽离出来做封装,然后通过组合的方式去拼装,就可以动态的修改行为了,提高了扩展,降低了耦合。

(2)工厂方法

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。工厂方法就是通过指定子类,让子类决定创建的对象。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PCZeLLiW-1634514353622)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210521171123981.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JLPm5fPT-1634514353623)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210521171133280.png)]

工厂方法就是通过指定子类,让子类决定创建的对象。让

package DesignPattern.factory.headFirstCase.factoryMethod;

public interface Pizza {
    String name();
    double pirce();
    double size();
    void make();
}
package DesignPattern.factory.headFirstCase.factoryMethod;

public class FruitPizza implements Pizza {
    @Override
    public String name() {
        return "水果披萨";
    }

    @Override
    public double pirce() {
        return 50.0f;
    }

    @Override
    public double size() {
        return 25.0f;
    }

    @Override
    public void make() {
        System.out.println("水果披萨制作完成");
    }
}
package DesignPattern.factory.headFirstCase.factoryMethod;

public class ChickenPizza implements Pizza {
    @Override
    public String name() {
        return "鸡肉披萨";
    }

    @Override
    public double pirce() {
        return 75.0f;
    }

    @Override
    public double size() {
        return 12.5f;
    }

    @Override
    public void make() {
        System.out.println("鸡肉披萨制作完成");
    }
}
package DesignPattern.factory.headFirstCase.factoryMethod;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class GuangZhouPizzaStore extends PizzaStore {
    @Override
    public Pizza createPizza(Class<?> clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Constructor<?> constructor = clazz.getDeclaredConstructor();
        Pizza pizza = (Pizza)constructor.newInstance();
        return pizza;
    }
}
package DesignPattern.factory.headFirstCase.factoryMethod;


import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ShenZhengPizzaStore extends PizzaStore {
    @Override
    public Pizza createPizza(Class<?> clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Constructor<?> constructor = clazz.getDeclaredConstructor();
        Pizza pizza = (Pizza)constructor.newInstance();
        return pizza;
    }
}

package DesignPattern.factory.headFirstCase.factoryMethod;

import DesignPattern.factory.headFirstCase.simpleFactory.SimpleFactory;

import java.lang.reflect.InvocationTargetException;

/**
 * 声明一个工厂方法,让pizzaStore的子类去决定需要创建什么类型的pizza
 */
public abstract class PizzaStore {
    private Pizza pizza;

    public Pizza orderPizza(Class<?> clazz){
        try {
            pizza = createPizza(clazz);
            pizza.make();
        }catch (Exception n){
            n.printStackTrace();
        }
        return pizza;
    }

    public abstract Pizza createPizza(Class<?> clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException;
}
package DesignPattern.factory.headFirstCase.factoryMethod;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class GuangZhouPizzaStore extends PizzaStore {
    @Override
    public Pizza createPizza(Class<?> clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Constructor<?> constructor = clazz.getDeclaredConstructor();
        Pizza pizza = (Pizza)constructor.newInstance();
        return pizza;
    }
}
package DesignPattern.factory.headFirstCase.factoryMethod;


import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ShenZhengPizzaStore extends PizzaStore {
    @Override
    public Pizza createPizza(Class<?> clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Constructor<?> constructor = clazz.getDeclaredConstructor();
        Pizza pizza = (Pizza)constructor.newInstance();
        return pizza;
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tGJWBD54-1634514353624)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210524092838817.png)]

工厂方法是通过抽象方法来扩展一个类,用来创建对象 的方法。从具体的类型解耦到抽象接口。

(3)抽象工厂

抽象工厂模式提供一个接口,用于创建相关或者依赖的家族。而不需要明确指定具体类。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3j1CIgc3-1634514353625)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210524094200602.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wsCbCP6e-1634514353626)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210524094215685.png)]

抽象工厂通过工厂方法将工厂从具体实例类型解耦成抽象的接口。通过组合对象来实现功能的继承。

例子:

披萨连锁店需要规范制作披萨的原料,于是创建原料工厂,将原料提供给加盟店,用来控制原料规范。

package DesignPattern.factory.headFirstCase.abstractFactory;
//原料抽象工厂
public abstract class RawMeterialFactory {
   abstract Doughy createDoughy();
   abstract Fruits createFruits();
   abstract Meat createMeat();
   abstract Sauce createSauce();
}

package DesignPattern.factory.headFirstCase.abstractFactory;

//产品
/**
 * 面团
 */
public interface Doughy {
     String getName();
}
package DesignPattern.factory.headFirstCase.abstractFactory;

/**
 * 水果
 */
public interface Fruits {
     String getName();
}
package DesignPattern.factory.headFirstCase.abstractFactory;

/**
 * 肉类
 */
public interface Meat {
    String getName();
}
package DesignPattern.factory.headFirstCase.abstractFactory;

/**
 * 酱料
 */
public interface Sauce {
    String getName();
}

package DesignPattern.factory.headFirstCase.abstractFactory;

public class ColdWaterDoughy implements Doughy{
    @Override
    public String getName() {
        return "冷水面团";
    }
}
package DesignPattern.factory.headFirstCase.abstractFactory;

public class HotWaterDoughy implements Doughy{
    @Override
    public String getName() {
        return "温水面团";
    }
}
package DesignPattern.factory.headFirstCase.abstractFactory;

public class AppleFruits implements Fruits {
    @Override
    public String getName() {
        return "苹果";
    }
}
package DesignPattern.factory.headFirstCase.abstractFactory;

public class BananaFruits implements Fruits {
    @Override
    public String getName() {
        return "香蕉";
    }
}
package DesignPattern.factory.headFirstCase.abstractFactory;

public class BeefMeat implements Meat {
    @Override
    public String getName() {
        return "牛肉";
    }
}
package DesignPattern.factory.headFirstCase.abstractFactory;

public class ChickenMeat implements Meat {
    @Override
    public String getName() {
        return "鸡肉";
    }
}
package DesignPattern.factory.headFirstCase.abstractFactory;

public class PeanutSauce implements Sauce{
    @Override
    public String getName() {
        return "花生酱";
    }
}
package DesignPattern.factory.headFirstCase.abstractFactory;

public class PepperSauce implements Sauce{
    @Override
    public String getName() {
        return "辣椒酱";
    }
}
package DesignPattern.factory.headFirstCase.abstractFactory;

public class ShenZhengFactory extends RawMeterialFactory {
    @Override
    public Doughy createDoughy() {
        return new ColdWaterDoughy();
    }

    @Override
    public Fruits createFruits() {
        return new BananaFruits();
    }

    @Override
    public Meat createMeat() {
        return new ChickenMeat();
    }

    @Override
    public Sauce createSauce() {
        return new PepperSauce();
    }
}
package DesignPattern.factory.headFirstCase.abstractFactory;

public class GuangZhouFactory extends RawMeterialFactory {
    @Override
    public Doughy createDoughy() {
        return new HotWaterDoughy();
    }

    @Override
    public Fruits createFruits() {
        return new AppleFruits();
    }

    @Override
    public Meat createMeat() {
        return new BeefMeat();
    }

    @Override
    public Sauce createSauce() {
        return new PeanutSauce();
    }
}
package DesignPattern.factory.headFirstCase.abstractFactory;

public interface Pizza {
    String name();
    double pirce();
    double size();
    void make();
}
package DesignPattern.factory.headFirstCase.abstractFactory;


public class ChickenPizza implements Pizza {
    private RawMeterialFactory rawMeterialFactory;

    public ChickenPizza(RawMeterialFactory rawMeterialFactory) {
        this.rawMeterialFactory = rawMeterialFactory;
    }

    @Override
    public String name() {
        return "鸡肉披萨";
    }

    @Override
    public double pirce() {
        return 75.0f;
    }

    @Override
    public double size() {
        return 12.5f;
    }

    @Override
    public void make() {
        Doughy doughy = rawMeterialFactory.createDoughy();
        Fruits fruits = rawMeterialFactory.createFruits();
        Meat meat = rawMeterialFactory.createMeat();
        Sauce sauce = rawMeterialFactory.createSauce();
        System.out.println("鸡肉披萨通过"+doughy.getName()+fruits.getName()+meat.getName()+sauce.getName()+"制作完成");
    }
}
package DesignPattern.factory.headFirstCase.abstractFactory;

public class FruitPizza implements Pizza {
    private RawMeterialFactory rawMeterialFactory;

    public FruitPizza(RawMeterialFactory rawMeterialFactory) {
        this.rawMeterialFactory = rawMeterialFactory;
    }

    @Override
    public String name() {
        return "水果披萨";
    }

    @Override
    public double pirce() {
        return 50.0f;
    }

    @Override
    public double size() {
        return 25.0f;
    }

    @Override
    public void make() {
        Doughy doughy = rawMeterialFactory.createDoughy();
        Fruits fruits = rawMeterialFactory.createFruits();
        Meat meat = rawMeterialFactory.createMeat();
        Sauce sauce = rawMeterialFactory.createSauce();
        System.out.println("水果披萨通过"+doughy.getName()+fruits.getName()+meat.getName()+sauce.getName()+"制作完成");
    }
}
package DesignPattern.factory.headFirstCase.abstractFactory;


import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ShenZhengPizzaStore extends PizzaStore {
    @Override
    public Pizza createPizza(Class<?> clazz,Class<? extends RawMeterialFactory> rawMeterialFactory)
            throws NoSuchMethodException, IllegalAccessException,
            InvocationTargetException, InstantiationException {

        Constructor<?> constructor = clazz.getDeclaredConstructor(rawMeterialFactory.getSuperclass());
        RawMeterialFactory factory = rawMeterialFactory.getDeclaredConstructor().newInstance();
        Pizza pizza = (Pizza)constructor.newInstance(factory);
        return pizza;
    }
}
package DesignPattern.factory.headFirstCase.abstractFactory;

public class GuangZhouFactory extends RawMeterialFactory {
    @Override
    public Doughy createDoughy() {
        return new HotWaterDoughy();
    }

    @Override
    public Fruits createFruits() {
        return new AppleFruits();
    }

    @Override
    public Meat createMeat() {
        return new BeefMeat();
    }

    @Override
    public Sauce createSauce() {
        return new PeanutSauce();
    }
}

package DesignPattern.factory.headFirstCase.abstractFactory;


public class Test {
    public static void main(String[] args) {
        PizzaStore pizzaStore = new ShenZhengPizzaStore();
        Pizza pizza = pizzaStore.orderPizza(FruitPizza.class,ShenZhengFactory.class);
        System.out.println("我在深圳披萨商店点了一份"+pizza.name()+pizza.pirce()+"元钱");
        pizzaStore = new GuangZhouPizzaStore();
        pizza = pizzaStore.orderPizza(ChickenPizza.class,GuangZhouFactory.class);
        System.out.println("我在广州披萨商店点了一份"+pizza.name()+pizza.pirce()+"元钱");
    }
}

五、单例模式
(1)概念:

确保一个类只有一个实例,且提供一个全局访问点。

(2)案例:
package DesignPattern.singleton;

/**
 * 懒汉模式,双重检查可以提高性能
 */
public class LazySingleCase {
    private volatile static LazySingleCase lazySingleCase = null;
    private LazySingleCase(){};

    public static LazySingleCase getInstance(){
        if(lazySingleCase == null){
            synchronized (LazySingleCase.class){
                if(lazySingleCase == null){
                    lazySingleCase = new LazySingleCase();
                }
            }
        }
        return lazySingleCase;
    }
}

package DesignPattern.singleton;

/**
 * 饿汉模式
 */
public class HungrySingleCase {
    private static HungrySingleCase hungrySingleCase = new HungrySingleCase();
    private HungrySingleCase(){};

    private HungrySingleCase getHungrySingleCase(){
        return  hungrySingleCase;
    }
}

六、命令模式
(1)概念:

将”请求“封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象,命令模式也支持可撤销的操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wIXbWejm-1634514353627)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210524152513433.png)]

命令模式将请求调用者和请求接受者进行了解耦,让请求调用者只需要调用接受者暴露的执行方法,而不用知道其实现细节。

将特定接受者和执行动作包装成命令对象,命令对象暴露出一个执行方法,调用者调用这个方法就可以执行相应的操作。

(2)案例:
package DesignPattern.command;

//特定接受者类
public interface Light {
    void on();

    void off();
}
package DesignPattern.command;

public class DrawingRoomLight implements Light {
    @Override
    public void on() {
        System.out.println("开启客厅灯");
    }

    @Override
    public void off() {
        System.out.println("关闭客厅灯");
    }
}
package DesignPattern.command;

public interface Music {
    void onSound();

    void playSong();

    void pauseSong();

    void offSound();
}
package DesignPattern.command;

public class SongRoom implements Music {
    @Override
    public void onSound() {
        System.out.println("打开音响");
    }

    @Override
    public void playSong() {
        System.out.println("播放Dj");
    }

    @Override
    public void pauseSong() {
        System.out.println("暂停DJ");
    }

    @Override
    public void offSound() {
        System.out.println("关闭音响");
    }
}
package DesignPattern.command;

//命令接口
public interface Command {
    void execute();
}
package DesignPattern.command;

public class LightOnCommand implements Command {
    private Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.on();
    }
}
package DesignPattern.command;

public class LightOffCommand implements Command{
    private Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.off();
    }
}
package DesignPattern.command;

public class MusicOnCommand implements Command {
    private Music music;

    public MusicOnCommand(Music music) {
        this.music = music;
    }

    @Override
    public void execute() {
        music.onSound();
        music.playSong();
    }
}
package DesignPattern.command;

public class MusicOffCommand implements Command {
    private Music music;

    public MusicOffCommand(Music music) {
        this.music = music;
    }

    @Override
    public void execute() {
        music.pauseSong();
        music.offSound();
    }
}
package DesignPattern.command;

//请求调用者
public class RemoteControl {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void clickBox(){
        command.execute();
    }

}
package DesignPattern.command;

public class Test {
    public static void main(String[] args) {
        Light light = new DrawingRoomLight();
        Music music = new SongRoom();
        Command lightOnCommand = new LightOnCommand(light);
        Command lightOffCommand = new LightOffCommand(light);
        Command musicOnCommand = new MusicOnCommand(music);
        Command musicOffCommand = new MusicOffCommand(music);
        RemoteControl remoteControl = new RemoteControl();
        remoteControl.setCommand(lightOnCommand);
        remoteControl.clickBox();
        remoteControl.setCommand(lightOffCommand);
        remoteControl.clickBox();
        remoteControl.setCommand(musicOnCommand);
        remoteControl.clickBox();
        remoteControl.setCommand(musicOffCommand);
        remoteControl.clickBox();
    }
}

(3)项目实例:

实际应用有日程安排,线程池,工作队列。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Chn8ZvCC-1634514353628)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210524172322841.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4AqsTfcZ-1634514353628)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210524172335609.png)]

七、适配器模式和外观模式
(1)概念:

将一个类的接口,转接成客户期望的另外一个接口,适配器让原本接口不兼容的类可以合作无间。

适配器将不兼容的接口变成兼容的接口,让客户从实现的接口解耦。适配器将变化的部分封装了起来,

客户就不必为了应付不同的接口而每次跟着修改 。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t8KdOVsl-1634514353630)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210524174358841.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aA4F8ugr-1634514353630)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210525093846117.png)]

(2)实例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lJf3l0RL-1634514353631)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210524174713376.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iB7QgWER-1634514353632)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210524174725231.png)]

package DesignPattern.adapter.HeadFirst;

public interface Duck {
    void quack();
    void fly();

}
package DesignPattern.adapter.HeadFirst;

public class MallardDuck implements Duck {
    @Override
    public void quack() {
        System.out.println("绿头鸭呱呱的叫");
    }

    @Override
    public void fly() {
        System.out.println("绿头鸭飞的远");
    }
}
package DesignPattern.adapter.HeadFirst;

public interface Turkey {
    void gobble();
    void fly();
}
package DesignPattern.adapter.HeadFirst;

public class WildTurKey implements Turkey {
    @Override
    public void gobble() {
        System.out.println("咯咯咯的叫");
    }

    @Override
    public void fly() {
        System.out.println("火鸡飞的不远");
    }
}
package DesignPattern.adapter.HeadFirst;

/**
 * 将火鸡假装成鸭子来用
 */
public class TurKeyAdapter implements Duck {
    private Turkey turkey;

    public TurKeyAdapter(Turkey turkey) {
        this.turkey = turkey;
    }

    @Override
    public void quack() {
        turkey.gobble();
    }

    @Override
    public void fly() {
        turkey.fly();
        turkey.fly();
        turkey.fly();
        turkey.fly();
        turkey.fly();
    }
}
package DesignPattern.adapter.HeadFirst;

public class Test {
    public static void main(String[] args) {
        TurKeyAdapter turKeyAdapter = new TurKeyAdapter(new WildTurKey());
        turKeyAdapter.quack();
        turKeyAdapter.fly();
    }
}

(3)外观模式概念:

提供一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层的接口,让子系统更容易的使用。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TZcnrIay-1634514353633)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210525101038143.png)]

(4)外观模式实例:家庭电影院
package DesignPattern.facade;

//子系统功能类
public class Amp {
    public void on(){
        System.out.println("打开功放");
    }

    public void setType(String type){
        System.out.println("功放类型:"+type);
    }

    public void setSurroundSound(){
        System.out.println("设置环绕立体声");
    }

    public void setVolume(int size){
        System.out.println("设置音量大小为:"+size);
    }

    public void off(){
        System.out.println("关闭功放");
    }
}
package DesignPattern.facade;

public class Dvd {
    public void on(){
        System.out.println("打开DVD");
    }

    public void play(String name){
        System.out.println("播放电源:"+name);
    }

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

    public void eject(){
        System.out.println("退出碟片");
    }

    public void off(){
        System.out.println("关闭DVD");
    }
}
package DesignPattern.facade;

public class Lights {
    public void dim(int num){
        System.out.println("灯光亮度调节至"+num);
    }

    public void on(){
        System.out.println("灯光打开");
    }
}
package DesignPattern.facade;

public class Popper {

    public void on(){
        System.out.println("打开爆米花机");
    }

    public void pop(){
        System.out.println("开始输送出爆米花");
    }

    public void off(){
        System.out.println("关闭爆米花机");
    }
}
package DesignPattern.facade;

public class Projector {
    public void on(){
        System.out.println("打开摄影机");
    }

    public void off(){
        System.out.println("关闭摄影机");
    }

    public void setInput(String type){
        System.out.println("设置的模式是"+type);
    }

    public void wideScreenMode(){
        System.out.println("开始播放");
    }
}
package DesignPattern.facade;

public class Sceen {
    public void down(){
        System.out.println("将电影屏幕放下");
    }

    public void up(){
        System.out.println("电影屏幕拉起");
    }
}

package DesignPattern.facade;

/**
 * 家庭电影院的外观模式,外观类
 */
public class HomeTheaterFacade {
    private Amp amp;
    private Dvd dvd;
    private Lights lights;
    private Popper popper;
    private Projector projector;
    private Sceen sceen;

    public HomeTheaterFacade(Amp amp, Dvd dvd, Lights lights, Popper popper, Projector projector, Sceen sceen) {
        this.amp = amp;
        this.dvd = dvd;
        this.lights = lights;
        this.popper = popper;
        this.projector = projector;
        this.sceen = sceen;
    }

    public void watchMovie(String movie){
        popper.on();
        popper.pop();
        lights.dim(10);
        sceen.down();
        projector.on();
        projector.wideScreenMode();
        amp.on();
        amp.setType("DVD");
        amp.setSurroundSound();
        amp.setVolume(5);
        dvd.on();
        dvd.play(movie);
    }

    public void endMovie(){
        popper.off();
        lights.on();
        sceen.up();
        projector.off();
        amp.off();
        dvd.stop();
        dvd.eject();
        dvd.off();
    }
}

package DesignPattern.facade;

public class Test {
    public static void main(String[] args) {
        Amp amp = new Amp();
        Dvd  dvd = new Dvd();
        Lights lights = new Lights();
        Popper popper = new Popper();
        Projector projector = new Projector();
        Sceen sceen = new Sceen();
        HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(amp,dvd,lights,popper,projector,sceen);
        homeTheaterFacade.watchMovie("钱学森");
        homeTheaterFacade.endMovie();
    }
}

(5)适配器、外观模式、装饰者模式差异性

适配器:将一个或者多个类或者接口包装成客户希望的接口,也就是将接口进行转换。

外观模式:将子系统的多个功能类,组合包装成一个外观类,外观类提供简单的接口给客户调用,将客户和子系统的具体功能类解耦。

装饰者:给对象赋予新的行为和功能,也就是将对象变成一个新的对象,但是还是同一个接口类型的类,以用来实现功能的扩展。

八、模板方法模式
(1)概念:

在一个方法内定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,

重新定义算法中的某些步骤。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bIUEG2Wx-1634514353634)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210525111930600.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZQJV0KKL-1634514353635)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210525132303046.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KUMNpVyO-1634514353636)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210525161855278.png)]

(2)实例:冲泡饮料
package DesignPattern.templateMethod;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public abstract class AbstractBeverages {

    //定义算法骨架,方法执行顺序
    public void makeBeverages(){
        boilWater();
        brew();
        if(whetherNeedCondiments()){
            addCondiments();
        }
        infundeCup();
    }

    //由子类必须实现的部分算法,定义为abstract
    public abstract void brew();

    public abstract void addCondiments();

    //公用方法
    public void boilWater(){
        System.out.println("将水烧开!");
    }

    public void infundeCup(){
        System.out.println("将饮料倒入杯子中");
    }

    //钩子函数,可以为空实现
    public boolean whetherNeedCondiments(){
        return true;
    }

    public String getUserInput(){
        String answer = null;
        System.out.println("你是否需要添加调味品? 需要/不需要");
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        try{
            answer = bufferedReader.readLine();
        }catch (IOException i){
            i.printStackTrace();
        }
        if(answer == null){
            return "不需要";
        }
        return answer;
    }
}
package DesignPattern.templateMethod;

public class CoffeeBeverages extends AbstractBeverages {
    @Override
    public void brew() {
        System.out.println("泡咖啡");
    }

    @Override
    public void addCondiments() {
        System.out.println("添加奶泡");
    }

    @Override
    public boolean whetherNeedCondiments() {
        String answer = getUserInput();
        if(answer == "需要"){
            return true;
        }else {
            return false;
        }
    }
}
package DesignPattern.templateMethod;

public class TeaBeverages extends AbstractBeverages {
    @Override
    public void brew() {
        System.out.println("泡茶");
    }

    @Override
    public void addCondiments() {
        System.out.println("添加糖块");
    }

    @Override
    public boolean whetherNeedCondiments() {
        String answer = getUserInput();
        if(answer == "需要"){
            return true;
        }else {
            return false;
        }
    }

}
package DesignPattern.templateMethod;

public class Test {
    public static void main(String[] args) {
        AbstractBeverages coffeeBeverages = new CoffeeBeverages();
        AbstractBeverages teaBeverages = new TeaBeverages();
        coffeeBeverages.makeBeverages();
        teaBeverages.makeBeverages();
    }
}

(3)项目运用案例:
一、数组的排序sort()

Arrays不是抽象类,mergeSort()方法看起来更像是策略模式,通过实现Compareable接口,

实现不同的比较算法,但是我认为他是模板方法,因为在mergeSort()方法中定义了compareTo(),swap()两个算法 的执行

顺序,同时compareTo()也是不完成的,由数组元素实现其方法。

public class Arrays {
   //这个是提供出来的访问的静态方法 
   public static void sort(Object[] a) {
        if (Arrays.LegacyMergeSort.userRequested) {
            legacyMergeSort(a);
        } else {
            ComparableTimSort.sort(a, 0, a.length, (Object[])null, 0, 0);
        }

    }
    
    private static void legacyMergeSort(Object[] a) {
        Object[] aux = (Object[])a.clone();
        mergeSort(aux, a, 0, a.length, 0);
    }
    
}
//这个是模板方法
private static void mergeSort(Object[] src, Object[] dest, int low, int high, int off) {
        int length = high - low;
        int destLow;
        int destHigh;
        if (length < 7) {
            for(destLow = low; destLow < high; ++destLow) {
                //要排序,必须让数组元素实现compareable 接口中的compareTo()方法
                for(destHigh = destLow; destHigh > low && ((Comparable)dest[destHigh - 1]).compareTo(dest[destHigh]) > 0; --destHigh) {
                    swap(dest, destHigh, destHigh - 1);
                }
            }

        } else {
            destLow = low;
            destHigh = high;
            low += off;
            high += off;
            int mid = low + high >>> 1;
            mergeSort(dest, src, low, mid, -off);
            mergeSort(dest, src, mid, high, -off);
            if (((Comparable)src[mid - 1]).compareTo(src[mid]) <= 0) {
                System.arraycopy(src, low, dest, destLow, length);
            } else {
                int i = destLow;
                int p = low;

                for(int q = mid; i < destHigh; ++i) {
                    if (q < high && (p >= mid || ((Comparable)src[p]).compareTo(src[q]) > 0)) {
                        dest[i] = src[q++];
                    } else {
                        dest[i] = src[p++];
                    }
                }

            }
        }
    }

    //交换值
    private static void swap(Object[] x, int a, int b) {
        Object t = x[a];
        x[a] = x[b];
        x[b] = t;
    }

二、spring ioc 容器创建
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {
    @Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			//对一些初始化工作,当环境对象不存在时,创建环境对象。
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//返回一个内部的BeanFactory,
            //obtainFreshBeanFactory()这个是抽象方法由子类负责实现
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				//设置一堆容器的属性,钩子函数,由子类来选择实现
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				//执行内部的BeanFactoryPostProcessor和自定义的
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				//注册BeanPostProcessors
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				//初始国际化
				initMessageSource();

				// Initialize event multicaster for this context.
				//初始化事件传播器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses
				//初始化特定上下文子类中的其他特殊bean,onRefresh是钩子函数,由子类来实现的算法
				onRefresh();

				// Check for listener beans and register them.
				//注册事件监听器
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				//创建单例Bean
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				//容器销毁处理
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}
}

//这是模板方法中的抽象方法,由子类来实现其具体的算法
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		return getBeanFactory();
	}
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
(4)模板方法和策略模式、工厂方法的差异

模板方法:定义算法的骨架,子类可以决定如何实现算法的某些步骤。

策略模式:定义算法族,每个算法类都封装了一个行为,行为可以互换,然后使用委托来决定采用哪一个行为。

工厂方法:由哪个具体类来实现算法。

九、迭代器和组合模式
(1)概念:

提供一个方法顺序访问一个聚合对象的各个元素,而又不暴露其内部的表示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T9AZ5d0H-1634514353637)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210526092259948.png)]

(2)实例:

餐厅合并,各菜单能由服务员统一遍历,而服务员不需要知道具体菜单是由什么数据结构实现的

package DesignPattern.iterator;
import java.util.Iterator;

//菜单接口
public interface Menu {
    Iterator createIterator();
}


//菜单实现类
package DesignPattern.iterator;
import java.util.Iterator;

public class DinerMenu implements Menu{
    private static final int Max_Size = 6;
    private int numberOfItems = 0;
    private MenuItem[] menuItems;

    public DinerMenu() {
        this.menuItems = new MenuItem[Max_Size];
        addItem(new MenuItem("牛肉套餐","牛肉加炖罐",false,45));
        addItem(new MenuItem("白切鸡套餐","白切鸡加炖罐",false,55));
        addItem(new MenuItem("酱肉套餐","酱肉加炖罐",false,35));
        addItem(new MenuItem("卤肉套餐","卤肉加炖罐",false,28));
        addItem(new MenuItem("时蔬套餐","时蔬加炖罐",true,25));
        addItem(new MenuItem("烧鸭套餐","烧鸭加炖罐",false,38));
    }

    public void addItem(MenuItem menuItem){
        if(numberOfItems <= Max_Size){
            menuItems[numberOfItems] = menuItem;
            numberOfItems++;
        }
    }

    @Override
    public Iterator createIterator() {
        return new DinerMenuIterator(menuItems);
    }
}

package DesignPattern.iterator;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class PancakeHouseMenu implements Menu{
    private List<MenuItem> pancakeList;

    public PancakeHouseMenu() {
        pancakeList = new ArrayList<>();
        addItem(new MenuItem("鸡蛋煎饼","往煎饼中添加鸡蛋",false,5.5));
        addItem(new MenuItem("原味煎饼","不添加任何佐料",true,3));
        addItem(new MenuItem("鸡柳煎饼","往煎饼中添加鸡柳",false,6.5));
        addItem(new MenuItem("猪肉煎饼","往煎饼中添加猪肉",false,7.5));
    }

    public void addItem(MenuItem menuItem){
        pancakeList.add(menuItem);
    }

    @Override
    public Iterator createIterator() {
        return pancakeList.iterator();
    }
}

//自定义数组迭代器
package DesignPattern.iterator;
import java.util.Iterator;

public class DinerMenuIterator implements Iterator {
    private MenuItem[] menuItems;
    private int position = 0;

    public DinerMenuIterator(MenuItem[] menuItems) {
        this.menuItems = menuItems;
    }

    @Override
    public boolean hasNext() {
        if(position >= menuItems .length || menuItems[position] == null){
            return false;
        }else {
            return true;
        }
    }

    @Override
    public Object next() {
        MenuItem menuItem = menuItems[position];
        position++;
        return menuItem;
    }

    @Override
    public void remove() {
        if(position <= 0){
            throw new IllegalArgumentException("集合内没有这个元素");
        }
        if(menuItems[position-1] != null){
            for(int i = position -1;i<(menuItems.length-1);i++){
                menuItems[i] = menuItems[i+1];
            }
            menuItems[menuItems.length-1] = null;
        }

    }

}
//菜单项详情
package DesignPattern.iterator;
public class MenuItem {
    private String name;
    private String description;
    private boolean vegetarain;
    double price;

    public MenuItem(String name, String description, boolean vegetarain, double price) {
        this.name = name;
        this.description = description;
        this.vegetarain = vegetarain;
        this.price = price;
    }

    public String getName() {
        return name;
    }

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

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public boolean isVegetarain() {
        return vegetarain;
    }

    public void setVegetarain(boolean vegetarain) {
        this.vegetarain = vegetarain;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}
package DesignPattern.iterator;

import java.util.Iterator;
import java.util.List;

//服务员
public class Waiter {
    private List<Menu> menuList;

    public Waiter(List<Menu> menuList) {
        this.menuList = menuList;
    }

    public void printMenu(){
        Iterator iterator = menuList.iterator();
        while(iterator.hasNext()){
            Menu menu = (Menu) iterator.next();
            printMenu(menu.createIterator());
        }
    }
    public void printMenu(Iterator iterator){
        while(iterator.hasNext()){
            MenuItem menuItem = (MenuItem) iterator.next();
            System.out.println("菜单项名称:"+menuItem.getName());
            System.out.println("菜单项详情:"+menuItem.getDescription());
            System.out.println("是否是素食:"+menuItem.isVegetarain());
            System.out.println("菜单项价格:"+menuItem.getPrice());
        }
    }
}

package DesignPattern.iterator;

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

public class Test {
    public static void main(String[] args) {
        List<Menu> menuList = new ArrayList<>();
        menuList.add(new DinerMenu());
        menuList.add(new PancakeHouseMenu());
        Waiter waiter = new Waiter(menuList);
        waiter.printMenu();
    }
}


(3)组合模式:

概念:允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。

比如菜单

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LICUR0xu-1634514353638)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210526105840539.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eEvIzmV4-1634514353639)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210526110120568.png)]

组合模式是违反了单一原则,一个类里有两个职责的方法,但是它增加了透明性,将对象组合成树形结构。

(4)组合模式实例:与适配器一起使用

菜单升级,一个主菜单,主菜单里包含多个子菜单,子菜单里也能还有子菜单

package DesignPattern.iterator.group;

import java.util.Iterator;
//抽象父组件
public abstract class MenuComponents {

    public void add(MenuComponents menuComponents){
        throw  new UnsupportedOperationException();
    }

    public void remove(MenuComponents menuComponents){
        throw new UnsupportedOperationException();
    }

    public String getName(){
        throw new UnsupportedOperationException();
    }

    public String getDescription(){
        throw new UnsupportedOperationException();
    }

    public double getPrice(){
        throw new UnsupportedOperationException();
    }

    public boolean isVegetarian(){
        throw new UnsupportedOperationException();
    }

    public void print(){
        throw new UnsupportedOperationException();
    }

    public MenuComponents getChild(int i){
        throw new UnsupportedOperationException();
    }

    public abstract Iterator iterator();
}

package DesignPattern.iterator.group;

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

//叶节点菜单组件
public class Menu extends MenuComponents {
    private List<MenuComponents> menuComponentsList;
    private String name;
    private String description;

    public Menu(String name, String description) {
        this.menuComponentsList = new ArrayList<>();
        this.name = name;
        this.description = description;
    }

    @Override
    public void add(MenuComponents menuComponents) {
        menuComponentsList.add(menuComponents);
    }

    @Override
    public void remove(MenuComponents menuComponents) {
        menuComponentsList.remove(menuComponents);
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getDescription() {
        return description;
    }

    @Override
    public void print() {
        System.out.println("菜单名称:"+getName()+" |菜单详情"+getDescription());
        Iterator<MenuComponents> iterator = menuComponentsList.iterator();
        while(iterator.hasNext()){
            MenuComponents menuComponents = iterator.next();
            menuComponents.print();
        }
    }

    @Override
    public MenuComponents getChild(int i) {
        return menuComponentsList.get(i);
    }

    @Override
    public Iterator iterator() {
        return  new CompositeIterator(menuComponentsList.iterator());
    }

}

package DesignPattern.iterator.group;

import java.util.Iterator;

//叶子节点组件
public class MenuItem extends MenuComponents {

    private String name;
    private String description;
    private boolean vegetarain;
    private double price;


    public MenuItem(String name, String description,  boolean vegetarain,double price) {
        this.name = name;
        this.description = description;
        this.vegetarain = vegetarain;
        this.price = price;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getDescription() {
        return description;
    }

    @Override
    public double getPrice() {
        return price;
    }

    @Override
    public boolean isVegetarian() {
        return vegetarain;
    }

    @Override
    public void print() {
        System.out.println("菜名:"+getName()+"  | 是否为素食:"+isVegetarian()+"  |菜的详情介绍:"+getDescription()+" |价格:"+getPrice());
    }

    @Override
    public Iterator iterator() {
        return new NullIterator();
    }

}

package DesignPattern.iterator.group;

import java.util.Iterator;

//叶子节点组件的空迭代器,因为叶子节点相当于空的叶节点
public class NullIterator implements Iterator {
    @Override
    public boolean hasNext() {
        return false;
    }

    @Override
    public Object next() {
        return null;
    }

    @Override
    public void remove() {
        throw  new UnsupportedOperationException();
    }
}

package DesignPattern.iterator.group;

import java.util.Iterator;
import java.util.Stack;

//叶节点迭代器
public class CompositeIterator implements Iterator {
    Stack stack = new Stack();

    public CompositeIterator(Iterator iterator){
        stack.push(iterator);
    }
    @Override
    public boolean hasNext() {
        if(stack.empty()){
            return false;
        }else {
            Iterator iterator = (Iterator) stack.peek();
            if(!iterator.hasNext()){
                stack.pop();
                return hasNext();
            }else{
                return true;
            }
        }
    }

    @Override
    public Object next() {
        if(hasNext()){
            Iterator iterator = (Iterator) stack.peek();
            MenuComponents menuComponents = (MenuComponents) iterator.next();
            if(menuComponents instanceof Menu){
                stack.push(menuComponents.iterator());
            }
            return menuComponents;
        }else{
            return null;
        }
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }
}

package DesignPattern.iterator.group;

import java.util.Iterator;

//服务员
public class Waiter {
    private MenuComponents menuComponents;

    public Waiter(MenuComponents menuComponents) {
        this.menuComponents = menuComponents;
    }
    public void printMenu(){
        menuComponents.print();
    }

    public void printVegetarain(){
        Iterator iterator = menuComponents.iterator();
        while(iterator.hasNext()){
            MenuComponents menuComponents = (MenuComponents) iterator.next();
            try{
                if(menuComponents.isVegetarian()){
                    menuComponents.print();
                }
            }catch (UnsupportedOperationException u){

            }
        }
    }
}

package DesignPattern.iterator.group;

public class GroupTest {
    public static void main(String[] args) {
        MenuComponents menu = new Menu("主菜单","所有菜单组合");
        MenuComponents pancakeHouseMenu = new Menu("早餐菜单","煎饼屋的菜单");
        MenuComponents dinerMenu = new Menu("午餐菜单","快餐菜单");
        MenuComponents dessertMenu = new Menu("甜点菜单","午餐后的甜点菜单");

        dessertMenu.add(new MenuItem("绿豆布丁","绿豆加糖加淀粉",true,22));
        dessertMenu.add(new MenuItem("红豆布丁","红豆加糖加淀粉",true,23));
        dessertMenu.add(new MenuItem("芒果布丁","芒果汁加淀粉",true,32));
        dessertMenu.add(new MenuItem("榴莲布丁","榴莲肉加淀粉",true,42));
        dinerMenu.add(new DesignPattern.iterator.group.MenuItem("牛肉套餐","牛肉加炖罐",false,45));
        dinerMenu.add(new DesignPattern.iterator.group.MenuItem("白切鸡套餐","白切鸡加炖罐",false,55));
        dinerMenu.add(new DesignPattern.iterator.group.MenuItem("酱肉套餐","酱肉加炖罐",false,35));
        dinerMenu.add(new DesignPattern.iterator.group.MenuItem("卤肉套餐","卤肉加炖罐",false,28));
        dinerMenu.add(new DesignPattern.iterator.group.MenuItem("时蔬套餐","时蔬加炖罐",true,25));
        dinerMenu.add(new DesignPattern.iterator.group.MenuItem("烧鸭套餐","烧鸭加炖罐",false,38));
        pancakeHouseMenu.add(new DesignPattern.iterator.group.MenuItem("鸡蛋煎饼","往煎饼中添加鸡蛋",false,5.5));
        pancakeHouseMenu.add(new DesignPattern.iterator.group.MenuItem("原味煎饼","不添加任何佐料",true,3));
        pancakeHouseMenu.add(new DesignPattern.iterator.group.MenuItem("鸡柳煎饼","往煎饼中添加鸡柳",false,6.5));
        pancakeHouseMenu.add(new DesignPattern.iterator.group.MenuItem("猪肉煎饼","往煎饼中添加猪肉",false,7.5));
        dinerMenu.add(dessertMenu);
        menu.add(pancakeHouseMenu);
        menu.add(dinerMenu);
        Waiter waiter = new Waiter(menu);
        waiter.printVegetarain();
    }
}



十、状态模式
(1)概念:

允许对象在内部状态改变时改变它的行为,对象看起来好像是修改了它的类。

状态模式可以在context中不用放置很多条件判断的替代方案。通过将行为包装进状态对象中,

你可以通过context内简单地改变状态对象来改变context 的行为。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-56IDs2mN-1634514353640)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210527154902316.png)]

(2)实例:糖果机案例
package DesignPattern.state;

//context类
public class CandyMachine {
    private  State soldStateout;
    private  State noMoneyState;
    private  State hasMoneyState;
    private  State soldState;
    private int count;
    private State state;

    public CandyMachine(int count) {
        this.soldStateout = new SoldStateout(this);
        this.noMoneyState = new NoMoneyState(this);
        this.hasMoneyState = new HasMoneyState(this);
        this.soldState = new SoldState(this);
        this.count = count;
        if(count > 0){
            state = noMoneyState;
        }
    }

    public void putMoney(){
        state.putMoney();
    }

    public void backMoney(){
        state.backMoney();
    }

    public void turnCrank(){
        state.rotate();
        state.dispense();
    }

    public void setState(State state){
        this.state = state;
    }

    public void releaseBall(){
        if(count > 0){
            count--;
        }
    }

    public void addCandy(){
        state.addCandy();
    }

    public State getSoldStateout() {
        return soldStateout;
    }

    public State getNoMoneyState() {
        return noMoneyState;
    }

    public State getHasMoneyState() {
        return hasMoneyState;
    }

    public State getSoldState() {
        return soldState;
    }

    public int getCount() {
        return count;
    }

    public State getState() {
        return state;
    }

    public void setCount(int count) {
        this.count = count;
    }
}
package DesignPattern.state;

//状态抽象类
public abstract class State {

    public void putMoney(){
        throw new UnsupportedOperationException();
    }

    public void backMoney(){
        throw new UnsupportedOperationException();
    }

    public void rotate(){
        throw new UnsupportedOperationException();
    }

    public void dispense(){
        throw new UnsupportedOperationException();
    }
    public void addCandy(){
        throw new UnsupportedOperationException();
    }
}
package DesignPattern.state;

//状态行为类
public class HasMoneyState extends State {
    private CandyMachine candyMachine;

    public HasMoneyState(CandyMachine candyMachine) {
        this.candyMachine = candyMachine;
    }

    @Override
    public void backMoney() {
        System.out.println("退款2元");
        candyMachine.setState(candyMachine.getNoMoneyState());
    }

    @Override
    public void rotate() {
        System.out.println("糖果机转动糖果");
        candyMachine.setState(candyMachine.getSoldState());
    }

}
package DesignPattern.state;

public class NoMoneyState extends State {
    private CandyMachine candyMachine;

    public NoMoneyState(CandyMachine candyMachine) {
        this.candyMachine = candyMachine;
    }

    @Override
    public void putMoney() {
        System.out.println("投入2元钱");
        candyMachine.setState(candyMachine.getHasMoneyState());
    }
}
package DesignPattern.state;

public class SoldState extends State {
    private CandyMachine candyMachine;

    public SoldState(CandyMachine candyMachine) {
        this.candyMachine = candyMachine;
    }

    @Override
    public void dispense() {
        candyMachine.releaseBall();
        if(candyMachine.getCount() > 0){
            candyMachine.setState(candyMachine.getNoMoneyState());
        }else{
            candyMachine.setState(candyMachine.getSoldStateout());
        }
    }
}
package DesignPattern.state;

public class SoldStateout extends State {
    private CandyMachine candyMachine;

    public SoldStateout(CandyMachine candyMachine) {
        this.candyMachine = candyMachine;
    }

    @Override
    public void addCandy(){
        candyMachine.setCount(20);
        candyMachine.setState(candyMachine.getNoMoneyState());
    }

}
package DesignPattern.state;

public class Test {
    public static void main(String[] args) {
        CandyMachine candyMachine = new CandyMachine(2);
        candyMachine.putMoney();
        candyMachine.turnCrank();
        candyMachine.putMoney();
        candyMachine.turnCrank();
        if(candyMachine.getState() == candyMachine.getSoldStateout()){
            candyMachine.addCandy();
        }
        candyMachine.putMoney();
        candyMachine.turnCrank();

        candyMachine.putMoney();
        candyMachine.turnCrank();
    }
}

十一、代理模式
(1)概念:

代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bJCUBfVU-1634514353641)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210531140059353.png)]

动态代理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UL4SaBPQ-1634514353642)(C:\Users\96979\AppData\Roaming\Typora\typora-user-images\image-20210531144053512.png)]

代理对象是为了控制对对象的访问,二是在创建开销大的对象时也可以同时做其他的事情。

(2)实例:

静态代理

package proxy;

/**
 * 静态代理
 */
public class StaticProxy {

    interface Iservice {
        void sayHello();
    }

    static class RealService implements  Iservice {

        @Override
        public void sayHello() {
            System.out.println("I'm RealService!");
        }
    }

    static class ProxyService implements Iservice {
        private RealService realService;

        public ProxyService(RealService realService) {
            this.realService = realService;
        }

        @Override
        public void sayHello() {
            realService.sayHello();
            System.out.println("I'm ProxyService!");
        }
    }

    public static void main(String[] args) {
        RealService realService = new RealService();
        ProxyService proxyService = new ProxyService(realService);
        proxyService.sayHello();
    }
}

jdk动态代理(接口代理)

package DesignPattern.proxy.jdkProxy;

public interface PersonBean {
    String getName();
    String getGender();
    String getInterests();
    int getHotOrNotRating();

    void setName(String name);
    void setGender(String gender);
    void setInterests(String interests);
    void setHotOrNotRating(int rating);
}

package DesignPattern.proxy.jdkProxy;

public class PersonBeanImpl implements PersonBean {

    private String name;
    private String gender;
    private String interests;
    private int rating;
    private int ratingCount = 0;

    public PersonBeanImpl(String name, String gender, String interests, int rating) {
        this.name = name;
        this.gender = gender;
        this.interests = interests;
        this.rating = rating;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getGender() {
        return gender;
    }

    @Override
    public String getInterests() {
        return interests;
    }

    @Override
    public int getHotOrNotRating() {
        if(rating == 0) {
            return 0;
        }else {
            return(rating/ratingCount);
        }
    }

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

    @Override
    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public void setInterests(String interests) {
        this.interests = interests;
    }

    @Override
    public void setHotOrNotRating(int rating) {
        this.rating += rating;
        ratingCount++;
    }
}
package DesignPattern.proxy.jdkProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

//控制来控制对真正对象方法的访问
public class NoOwerInvocationHandle implements InvocationHandler {
    private PersonBean personBean;

    public NoOwerInvocationHandle(PersonBean personBean) {
        this.personBean = personBean;
    }

    
    @Override
    public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable {
        if(method.getName().startsWith("get")){
            return method.invoke(personBean,objects);
        }else if(method.getName().equals("setHotOrNotRating")){
            return method.invoke(personBean,objects);
        }else if(method.getName().startsWith("set")){
            throw new IllegalAccessException();
        }
        return null;
    }
}
package DesignPattern.proxy.jdkProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class OwerInvocationHandle implements InvocationHandler {
    private PersonBean personBean;

    public OwerInvocationHandle(PersonBean personBean) {
        this.personBean = personBean;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable {
        if(method.getName().startsWith("get")){
            return method.invoke(personBean,objects);
        }else if(method.getName().equals("setHotOrNotRating")){
            throw new IllegalAccessException();
        }else if(method.getName().startsWith("set")){
            return method.invoke(personBean,objects);
        }
        return null;
    }
}
package DesignPattern.proxy.jdkProxy;

public class Test {
    public static void main(String[] args) {
       PersonBean personBean = new PersonBeanImpl("王五", "男", "打篮球", 1);
        PersonBean proxy = (PersonBean) java.lang.reflect.Proxy.newProxyInstance(
                personBean.getClass().getClassLoader(), personBean.getClass().getInterfaces(), new OwerInvocationHandle(personBean)
        );
        System.out.println(proxy.getName());
        proxy.setHotOrNotRating(1);

        PersonBean personBean1 = new PersonBeanImpl("李勤", "女", "踢足球", 2);
        PersonBean proxy1 = (PersonBean) java.lang.reflect.Proxy.newProxyInstance(
                personBean1.getClass().getClassLoader(), personBean1.getClass().getInterfaces(), new NoOwerInvocationHandle(personBean1)
        );
        System.out.println(proxy1.getName());
        proxy1.setHotOrNotRating(1);
        System.out.println(proxy1.getHotOrNotRating());
        proxy1.setInterests("打羽毛球");
    }


}

cglib代理(代理类继承被代理类)

package proxy;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 *java sdk 动态代理的局限是只能为接口创建代理,返回的代理对象也只能转换为接口类型
 * 要实现不是接口的代理需要用到第三方的类库,cglib,它是通过继承实现的,它也是动态创建一个类,
 * 但这个类的父类是被代理的类,代理类重写父类的所有public非final方法,改为调用Callback中的相关方法
 */
public class SimpleCGLBDynamicsDemo {

    static class RealSerice {
        public void sayHello(){
            System.out.println("RealService say hello !!");
        }
    }

    static class SimpleInterceptor implements MethodInterceptor {

        @Override
        public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println("entering" + method.getName());
            Object result = methodProxy.invokeSuper(o,args);
            System.out.println("leaving" + method.getName());
            return  result;
        }
    }

    private static <T> T getProxy(Class<T> cls){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(cls);
        enhancer.setCallback(new SimpleInterceptor());
        return  (T) enhancer.create();
    }

    public static void main(String[] args) {
         RealSerice realSericeProxy = getProxy(RealSerice.class);
         realSericeProxy.sayHello();
    }
}

十二、复合设计模式

(1)概念:一个解决方案中结合两个或者多个模式,以解决一般或者重复发生

十三、各设计模式的精练的话术
(1)策略模式:

封装可互换的行为,并使用委托(具体子类)决定使用哪一个。代替继承的方案。

(2)观察者模式:

某个状态改变时,允许一群对象能被通知到。

(3)装饰者模式:

一个对象被多个相同类型的装饰类进行包装,这个包装好的类具有新的行为和责任。

(4)工厂模式:

将对象创建的变化的部分抽出来生成新的工厂类。

(5)单例模式:

一个类只能被创建一次。

(6)命令模式:

将命令和执行者包装成一个命令对象,然后曝出一个简单接口去执行。

(7)适配器:

改变一个或者多个接口。

(8)外观模式:

简化一群类的接口

(9)模板方法模式:

定义一个算法骨架,算法步骤中的一部分算法由子类来实现。

(10)迭代器模式:

提供一个方法来遍历集合,而无需暴露集合的实现。

(11)组合模式:

将对象组合成整体/部分的结构,客户就可以对对象的集合和个别对象一视同仁

(12)状态模式:

封装基于状态的行为,并将行为委托到当前状态。将代码从复杂的条件判断中解耦出来,通过改变内部对象的状态来改变行为。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值