GOF设计模式

在这里插入图片描述

在这里插入图片描述

============================================================

创造类

单例模式(Singleton Pattern)

确保一个类只有一个实例,而且自行实例化,并向整个系统提供这个实例
在这里插入图片描述

/**
 * 饿汉式
 */
public class SingletonPattern {
    private static final SingletonPattern sinleton = new SingletonPattern();

    /**
     * 构造器私有化
     */
    private SingletonPattern(){

    }
    public synchronized static SingletonPattern getInstance(){
        return sinleton;
    }
}
/**
 * 懒汉式
 */
public class SingletonPattern2 {

    private static SingletonPattern2 singletonPattern2 = null;

    private SingletonPattern2(){

    }

    public static synchronized SingletonPattern2 getInstance(){
        if (singletonPattern2 == null){
            singletonPattern2 = new SingletonPattern2();
        }
        return singletonPattern2;
    }
}
public class Client {
    public static void main(String[] args) {
        SingletonPattern s1 = SingletonPattern.getInstance();
        SingletonPattern s2 = SingletonPattern.getInstance();

        System.out.println(s1 == s2);

        SingletonPattern2 s3 = SingletonPattern2.getInstance();
        SingletonPattern2 s4 = SingletonPattern2.getInstance();

        System.out.println(s3 == s4);
    }
}

登记式单例类

克服饿汉式或懒汉式单例类不可继承的缺点

public class RegSingleton{

	static private HashMap m_registry = new HashMap();
	static{
		RegSington x = new RegSingleton();
		m_registry.put(x.getClass().getName(),x);
	}
	
	//当前类的成员与继承该类的类才能访问
	protected RegSingleton(){}

	static public RegSingleton getInstance(String name){
		if(name == null){
			name = "com.xxx.RegSingleton";
		}
		if(m_registry.get(name) == null){
			try{
				m_registry.put(name,Class.forName(name).newInstance());
			}catch(Exception e){
				System.out.println("Error Happened");
			}
		}
		return (RegSingleton)(m_registry.get(name));
	}

	public String about(){
		return "Hello,I am RegSingleton";
	}
}
public class RegSingletonChild extends RegSingleton{

	public RegSingletonChild(){}

	static public RegSingletonChild getInstance(){
		return (RegSigletonChild)RegSinglelenton.getInstance("com.xxx.RegSinletonChild");
	}

	public String about(){
		return "Hello,I am RegSingletonChild";
	}
}

简单工厂模式

简单工厂模式通常就是这样,一个工厂类 XxxFactory,里面有一个静态方法,根据我们不同的参数,返回不同的派生自同一个父类(或实现同一接口)的实例对象

public interface Car{
	public void drive();
}

public class Benz implements Car{
	public void drive(){
		System.out.println("驾驶奔驰");
	}
}
public class Bmw implements Car{
	public void drive(){
		System.out.println("驾驶宝马")
	}
}

/**
	简单工厂
	根据传入的不同参数创建不同的实例对象
*/
public class Driver{
	public static Car driverCar(String s) throws Exception{
		if(s.equalsIgnore("Benz")){
			return new Benz();
		}else if(s.equalsIgnore("Bmw"){
			return new Bmw();
		}
	}
}

public class Client{
	public static void main(String[] args){
		Car car = Driver.dirverCar("benz");
		car.driver();
	}
}

案例二:

public class FoodFactory{
	
	public static Food makeFood(String name){
		
		if(name.equals("noodle")){
			Food noodle = new LanzhouNoodle();
			noodle.addSpicy("more");
			return noodle;
		} else if (name.equals("chicken")) {
            Food chicken = new HuangMenChicken();
            chicken.addCondiment("potato");
            return chicken;
        } else {
            return null;
        }
	}
}

工厂方法模式(Factory Method Pattern)

定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使得一个类的实例化延迟到其子类
在这里插入图片描述

/**
	抽象工厂角色
*/
public interface Driver{ 
 	public Car driverCar(); 
}

/**
	子类决定实例化哪一个类
*/
public class BenzDriver implements Driver{ 
	 public Car driverCar(){ 
	 	return new Benz(); 
 	} 
} 
public class BmwDriver implements Driver{ 
	 public Car driverCar() { 
		return new Bmw(); 
	 } 
}

public class Client{
	public static void main(String[] args){
		Driver driver = new BenzDriver();
		Car car = driver.driverCar();
		car.drive();
	}
}

案例二:
在这里插入图片描述

public interface FoodFactory{
	Food makeFood(String name);
}

public class ChineseFoodFactory implements FoodFactory{
	
	@Override
	public Food makeFood(String name){
	
		if(name.equals("A")){
			return new ChineseFoodA();
		}else if(name.dquals("B")){
			return new ChineseFoodB();
		}else{
			return null;
		}
	}
}

public class AmericanFoodFactory implements FoodFactory{
	
	@Override
	public Food makeFood(String name){
	
		if (name.equals("A")) {
            return new AmericanFoodA();
        } else if (name.equals("B")) {
            return new AmericanFoodB();
        } else {
            return null;
        }
	}
}
public class APP{
	
	public static void main(Stirng[] args){
		//先选择一个具体的工厂
		Factory factory = new ChineseFoodFactory();

		//再选择具体的
		Food food = factory.makeFood("A");
	}
}

抽象工厂模式(Abstract Factory Pattern)

为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类
在这里插入图片描述

/**
	人类
	白种人、黑种人、黄种人
*/
public interface Human {
	//每个人种都有相应的颜色
	public void getColor();
	//人类会说话
	public void talk();
	//每个人都有性别
	public void getSex();
}

public abstract class AbstractWhiteHuman implements Human {
	//白色人种的皮肤颜色是白色的
	public void getColor(){
		System.out.println("白色人种的皮肤颜色是白色的!");
	}
	//白色人种讲话
	public void talk() {
		System.out.println("白色人种会说话,一般说的都是单字节。");
	}
}
public abstract class AbstractBlackHuman implements Human {
	public void getColor(){
		System.out.println("黑色人种的皮肤颜色是黑色的!");
	}
	public void talk() {
		System.out.println("黑人会说话,一般人听不懂。");
	}
}
public abstract class AbstractYellowHuman implements Human {
	public void getColor(){
		System.out.println("黄色人种的皮肤颜色是黄色的!");
	}
	public void talk() {
		System.out.println("黄色人种会说话,一般说的都是双字节。");
	}
}

/**
	白种人、黑种人、黄种人
	白女、白男,黑女、黑男,黄女、黄男
*/
public class FemaleYellowHuman extends AbstractYellowHuman {
	//黄人女性
	public void getSex() {
		System.out.println("黄人女性");
	}
}
public class MaleYellowHuman extends AbstractYellowHuman {
	//黄人男性
	public void getSex() {
		System.out.println("黄人男性");
	}
}


/**
	人口生产厂
	男人:黄、白、黑
	女人:黄、白、黑
*/
public interface HumanFactory {
	//制造一个黄色人种
	public Human createYellowHuman();
	//制造一个白色人种
	public Human createWhiteHuman();
	//制造一个黑色人种
	public Human createBlackHuman();
}

public class FemaleFactory implements HumanFactory {
	//生产出黑人女性
	public Human createBlackHuman() {
		return new FemaleBlackHuman();
	}
	//生产出白人女性
	public Human createWhiteHuman() {
		return new FemaleWhiteHuman();
	}
	//生产出黄人女性
	public Human createYellowHuman() {
		return new FemaleYellowHuman();
	}
}
public class MaleFactory implements HumanFactory {
	//生产出黑人男性
	public Human createBlackHuman() {
		return new MaleBlackHuman();
	}
	//生产出白人男性
	public Human createWhiteHuman() {
		return new MaleWhiteHuman();
	}
	//生产出黄人男性
	public Human createYellowHuman() {
		return new MaleYellowHuman();
	}
}

public class NvWa {
	public static void main(String[] args) {
		//第一条生产线,男性生产线
		HumanFactory maleHumanFactory = new MaleFactory();
		//第二条生产线,女性生产线
		HumanFactory femaleHumanFactory = new FemaleFactory();
		//生产线建立完毕,开始生产人了:
		Human maleYellowHuman = maleHumanFactory.createYellowHuman();
		Human femaleYellowHuman = femaleHumanFactory.createYellowHuman();
		System.out.println("---生产一个黄色女性---");
		
		femaleYellowHuman.getColor();
		femaleYellowHuman.talk();
		femaleYellowHuman.getSex();
		System.out.println("\n---生产一个黄色男性---");
		
		maleYellowHuman.getColor();
		maleYellowHuman.talk();
		maleYellowHuman.getSex();
		/*
		* ......
		* 后面继续创建
		*/
	}
}

案例二:
在这里插入图片描述

public static void main(String[] args){
	
	//选一个大厂(生产CPU/主板/硬盘)
	ComputerFactory cf = new AmdFactory();
	
	CPU cpu = cf.makeCPU();
	MainBoard board = cf.makeMainBoard();
	HardDisk hardDisk = cf.makeHardDisk();

	//将同一个工厂出来的CPU/主板/硬盘组装
	Computer result = new Computer(cpu,board,hardDisk);
}

建造者模式(Builder Pattern)

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
在这里插入图片描述

在这里插入图片描述

/**
	汽车模型
*/
public abstract class CarModel {
    //这个参数是各个基本方法执行的顺序
    private ArrayList<String> sequence = new ArrayList<String>();

    //模型是启动开始跑了
    protected abstract void start();

    //能发动,还要能停下来,那才是真本事
    protected abstract void stop();

    //喇叭会出声音,是滴滴叫,还是哔哔叫
    protected abstract void alarm();

    //引擎会轰隆隆地响,不响那是假的
    protected abstract void engineBoom();

    //那模型应该会跑吧,别管是人推的,还是电力驱动,总之要会跑
    final public void run() {
        //循环一边,谁在前,就先执行谁
        for (int i = 0; i < this.sequence.size(); i++) {
            String actionName = this.sequence.get(i);

            if (actionName.equalsIgnoreCase("start")) {
                this.start(); //启动汽车
            } else if (actionName.equalsIgnoreCase("stop")) {
                this.stop(); //停止汽车
            } else if (actionName.equalsIgnoreCase("alarm")) {
                this.alarm(); //喇叭开始叫了
            } else if (actionName.equalsIgnoreCase("engine boom")) {
                //如果是engine boom关键字
                this.engineBoom(); //引擎开始轰鸣
            }
        }
    }

    //把传递过来的值传递到类内
    final public void setSequence(ArrayList sequence) {
        this.sequence = sequence;
    }
}

/**
	奔驰
*/
public class BenzModel extends CarModel {
    protected void alarm() {
        System.out.println("奔驰车的喇叭声音是这个样子的...");
    }

    protected void engineBoom() {
        System.out.println("奔驰车的引擎是这个声音的...");
    }

    protected void start() {
        System.out.println("奔驰车跑起来是这个样子的...");
    }

    protected void stop() {
        System.out.println("奔驰车应该这样停车...");
    }
}

/**
	宝马
*/
public class BMWModel extends CarModel {
    protected void alarm() {
        System.out.println("宝马车的喇叭声音是这个样子的...");
    }

    protected void engineBoom() {
        System.out.println("宝马车的引擎是这个声音的...");
    }

    protected void start() {
        System.out.println("宝马车跑起来是这个样子的...");
    }

    protected void stop() {
        System.out.println("宝马车应该这样停车...");
    }
}

/**
	汽车组装:建造者模型
*/
public abstract class CarBuilder {
	//建造一个模型,你要给我一个顺序要求,就是组装顺序
	public abstract void setSequence(ArrayList<String> sequence);
	//设置完毕顺序后,就可以直接拿到这个车辆模型
	public abstract CarModel getCarModel();
}

public class BenzBuilder extends CarBuilder {
	private BenzModel benz = new BenzModel();
	public CarModel getCarModel() {
		return this.benz;
	}
	public void setSequence(ArrayList<String> sequence) {
		this.benz.setSequence(sequence);
	}
}
public class BMWBuilder extends CarBuilder {
	private BMWModel bmw = new BMWModel();
	public CarModel getCarModel() {
		return this.bmw;
	}
	public void setSequence(ArrayList<String> sequence) {
		this.bmw.setSequence(sequence);
	}
}

public class Client {
    public static void main(String[] args) {
        /*
        * 客户告诉XX公司,我要这样一个模型,然后XX公司就告诉我老大
        * 说要这样一个模型,这样一个顺序,然后我就来制造
        */

        //存放run的顺序
        ArrayList<String> sequence = new ArrayList<String>();
        sequence.add("engine boom"); //客户要求,run时候时候先发动引擎
        sequence.add("start"); //启动起来
        sequence.add("stop"); //开了一段就停下来
                              //要一个奔驰车:

        BenzBuilder benzBuilder = new BenzBuilder();
        //把顺序给这个builder类,制造出这样一个车出来
        benzBuilder.setSequence(sequence);

        //制造出一个奔驰车
        BenzModel benz = (BenzModel) benzBuilder.getCarModel();
        //奔驰车跑一下看看
        benz.run();
    }
}


链式建造者

class User{
	private String name;
	private String password;
	private String nickName;
	private int age;

	private User(String name,String password,String nickName,int age){
		this.name = name;
		this.password = password;
		this.nickName = nickName;
		this.age = age;
	}
	
	public static UserBuilder builder(){ //返回内部类实例
		return new UserBuilder();
	}

	//内部类
	public static class UserBuilder{
		private String name;
		private String pasword;
		private String nickName;
		private int age;

		private UserBuilder(){

		}

		//链式调用设置各个属性,返回this,及UserBuilder
		public UserBuilder name(String name){
			this.name = name;
			return this;
		}
		public UserBuilder password(String password){
			this.password = password;
			return this;
		}
		public UserBuilder nickName(String nickName){
			this.nickName = nickName;
			return this;
		}
		public UserBuilder age(int age){
			this.age = age;
			return this;
		}

		//将UserBuilder中设置好的属性复制到User中
		public User build(){
			if(name == null || password == null){
				throw new RuntimeException("用户名和密码必填");
			}
			if(age <= 0 || age >= 150){
				throw new RuntimeException("年龄不合法");
			}
			if(nickName == null){
				nickName = name;
			}
			return new User(name,password,nickName,age);
		}
	}
}


public class APP{
	public static void main(String[] args){
		User u = User.builder().name("foo")
			.password("123")
			.age(23)
			.build();
	}
}

案例二:

先把所有的属性都设置给 Builder,然后 build() 方法的时候,将这些属性复制给实际产生的对象。
当属性很多,而且有些必填,有些选填的时候,这个模式会使代码清晰很多。我们可以在 Builder 的构造方法中强制让调用者提供必填字段,还有,在 build() 方法中校验各个参数比在 User 的构造方法中校验,代码要优雅一些

/**
	属性
	有参构造器私有化
	静态内部,返回一个静态内部类的对象
	静态内部类
		和外部类一模一样的属性
		私有无参构造器
		公共链式调用构造器,设置每个属性,返回this
		build方法,验证属性的合法成功后,返回外部构造器创建的对象
*/
class User{
	
	// 下面是“一堆”的属性
    private String name;
    private String password;
    private String nickName;
    private int age;

    // 构造方法私有化,不然客户端就会直接调用构造方法了
    private User(String name, String password, String nickName, int age) {
        this.name = name;
        this.password = password;
        this.nickName = nickName;
        this.age = age;
    }
    // 静态方法,用于生成一个 Builder,这个不一定要有,不过写这个方法是一个很好的习惯,
    // 有些代码要求别人写 new User.UserBuilder().a()...build() 看上去就没那么好
    public static UserBuilder builder() {
        return new UserBuilder();
    }

    public static class UserBuilder {
        // 下面是和 User 一模一样的一堆属性
        private String  name;
        private String password;
        private String nickName;
        private int age;

        private UserBuilder() {
        }

        // 链式调用设置各个属性值,返回 this,即 UserBuilder
        public UserBuilder name(String name) {
            this.name = name;
            return this;
        }

        public UserBuilder password(String password) {
            this.password = password;
            return this;
        }

        public UserBuilder nickName(String nickName) {
            this.nickName = nickName;
            return this;
        }

        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }

        // build() 方法负责将 UserBuilder 中设置好的属性“复制”到 User 中。
        // 当然,可以在 “复制” 之前做点检验
        public User build() {
            if (name == null || password == null) {
                throw new RuntimeException("用户名和密码必填");
            }
            if (age <= 0 || age >= 150) {
                throw new RuntimeException("年龄不合法");
            }
            // 还可以做赋予”默认值“的功能
            if (nickName == null) {
                nickName = name;
            }
            return new User(name, password, nickName, age);
        }
    }
}
public class APP{
	public static void main(String[] args){
		User u = User.builder() //调用内部静态类
			.name("foo")
			.password("123")
			.age(25)
			.build();
	}
}

原型模式(Prototype Pattern)

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
在这里插入图片描述

在这里插入图片描述

案例1

/**
	具体原型角色,
	这里省略抽象原型角色
*/
public class EnemyPlane implements Cloneable{
	private int x;
	private int y = 0;
	
	public EnemyPlane(int x){
		this.x = x;
	}
	public int getX(){
		return x;
	}
	public int getY(){
		return y;
	}
	public void fly(){ //纵坐标改变,敌机飞
		y++;
	}
	public void setX(int x){ //克隆的实例重新修改X坐标
		this.x = x;
	}
	
	//重写克隆方法,调用了父类Object的克隆方法,这里JVM会进行内存操作直接拷贝原始数据流
	@Override
    public EnemyPlane clone() throws CloneNotSupportedException {
        return (EnemyPlane)super.clone();
    }
}


public class EnemyPlaneFactory {
    //此处用痴汉模式造一个敌机原型
    private static EnemyPlane protoType = new EnemyPlane(200);

    //获取敌机克隆实例
    public static EnemyPlane getInstance(int x){
        EnemyPlane clone = protoType.clone();//复制原型机
        clone.setX(x);//重新设置克隆机的x坐标
        return clone;
    }
}

案例2

public class Mail implements Cloneable{
	//收件人
	private String receiver;
	//邮件名称
	private String subject;
	//称谓
	private String appellation;
	//邮件内容
	private String contxt;
	//邮件的尾部,一般都是加上"XXX版权所有"等信息
	private String tail;
	
	//构造函数
	public Mail(AdvTemplate advTemplate){
		this.contxt = advTemplate.getAdvContext();
		this.subject = advTemplate.getAdvSubject();
	}
	@Override
	public Mail clone(){
		Mail mail =null;
		try {
		mail = (Mail)super.clone();
		} catch (CloneNotSupportedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
		}
		return mail;
	}
	
	//以下为getter/setter方法
	public String getReceiver() {
		return receiver;
	}
	public void setReceiver(String receiver) {
		this.receiver = receiver;
	}
	public String getSubject() {
		return subject;
	}
	public void setSubject(String subject) {
		this.subject = subject;
	}
	public String getAppellation() {
		return appellation;
	}
	public void setAppellation(String appellation) {
		this.appellation = appellation;
	}
	public String getContxt() {
		return contxt;
	}
	public void setContxt(String contxt) {
		this.contxt = contxt;
	}
	public String getTail() {
		return tail;
	}
	public void setTail(String tail) {
		this.tail = tail;
	}
}


public class Client {
	//发送账单的数量,这个值是从数据库中获得
	private static int MAX_COUNT = 6;
	public static void main(String[] args) {
		//模拟发送邮件
		int i=0;
		//把模板定义出来,这个是从数据中获得
		Mail mail = new Mail(new AdvTemplate());
		mail.setTail("XX银行版权所有");
		while(i<MAX_COUNT){
			//以下是每封邮件不同的地方
			Mail cloneMail = mail.clone();
			cloneMail.setAppellation(getRandString(5)+" 先生(女士)");
			cloneMail.setReceiver(getRandString(5)+"@"+getRandString(8)+".com");
			//然后发送邮件
			sendMail(cloneMail);
			i++;
		}
	}
}

迭代器模式(Iterator Pattern)

也叫做游标(Cursor)模式,提供一种方法访问一个容器对象中各个元素,而又不需要暴露该对象的内部细节
在这里插入图片描述

在这里插入图片描述

案例1:

/**
	迭代器接口标准
*/
public interface Iterator<E> {
    E next();//返回下一个元素
    boolean hasNext();//是否还有下一个元素
}

/**
	行车记录仪
*/
public class DrivingRecorder {
    private int index = -1;// 当前记录位置
    private String[] records = new String[10];// 假设只能记录10条视频

    public void append(String record) {
        if (index == 9) {// 循环覆盖
            index = 0;
        } else {
            index++;
        }
        records[index] = record;
    }

    public Iterator<String> iterator() { //JDK中util包自带的,返回一个迭代器
        return new Itr();
    }

    private class Itr implements Iterator<String> {
        int cursor = index;// 迭代器游标,不染指原始游标。
        int loopCount = 0;

        @Override
        public boolean hasNext() {
            return loopCount < 10;
        }

        @Override
        public String next() {
            int i = cursor;// 记录即将返回的游标位置
            if (cursor == 0) {
                cursor = 9;
            } else {
                cursor--;
            }
            loopCount++;
            return records[i];
        }
    };
}

public class Client {
    public static void main(String[] args) {
        DrivingRecorder dr = new DrivingRecorder();
        // 假设记录了12条视频
        for (int i = 0; i < 12; i++) {
            dr.append("视频_" + i);
        }
        //用户要获取交通事故视频,定义事故列表。
        List<String> accidents = new ArrayList<>();
        //用户拿到迭代器
        Iterator<String> it = dr.iterator();

        while (it.hasNext()) {//如果还有下一条则继续迭代
            String video = it.next();
            System.out.println(video);
            //用户翻看视频发现10和8可作为证据。
            if("视频_10".equals(video) || "视频_8".equals(video)){
                accidents.add(video);
            }
        }
        //拿到两个视频集accidents交给交警查看。
        System.out.println("事故证据:" + accidents);
        /*
        视频_11
        视频_10
        视频_9
        视频_8
        视频_7
        视频_6
        视频_5
        视频_4
        视频_3
        视频_2 
        事故证据:[视频_10, 视频_8]
        */
    }
}

案例2

/**
	迭代器角色接口
*/
public interface IProject {
	public void add(String name,int num,int cost);
	//从老板这里看到的就是项目信息
	public String getProjectInfo();
	//获得一个可以被遍历的对象
	public IProjectIterator iterator();
}
public class Project implements IProject {
	//定义一个项目列表,说有的项目都放在这里
	private ArrayList<IProject> projectList = new ArrayList<IProject>();
	//项目名称
	private String name = "";
	//项目成员数量
	private int num = 0;
	//项目费用
	private int cost = 0;
	
	//增加项目
	public void add(String name,int num,int cost){
		this.projectList.add(new Project(name,num,cost));
	}
	
	//定义一个构造函数,把所有老板需要看到的信息存储起来
	public Project(String name,int num,int cost){
		//赋值到类的成员变量中
		this.name = name;
		this.num = num;
		this.cost=cost;
	}
	
	//得到项目的信息
	public String getProjectInfo() {
		String info = "";
		//获得项目的名称
		info = info+ "项目名称是:" + this.name;
		//获得项目人数
		info = info + "\t项目人数: "+ this.num;
		//项目费用
		info = info+ "\t 项目费用:"+ this.cost;
		return info;
	}

	//产生一个遍历对象
	public IProjectIterator iterator(){
		return new ProjectIterator(this.projectList);
	}
}

/**
	迭代器接口
*/
public interface IProjectIterator extends Iterator {
}
public class ProjectIterator implements IProjectIterator {
	//所有的项目都放在ArrayList中
	private ArrayList<IProject> projectList = new ArrayList<IProject>();
	private int currentItem = 0;
	//构造函数传入projectList
	public ProjectIterator(ArrayList<IProject> projectList){
		this.projectList = projectList;
	}
	//判断是否还有元素,必须实现
	public boolean hasNext() {
		//定义一个返回值
		boolean b = true;
		if(this.currentItem>=projectList.size()||this.projectList.get(this.currentItem)==null){
			b =false;
		}
		return b;
	}
	//取得下一个值
	public IProject next() {
		return (IProject)this.projectList.get(this.currentItem++);
	}
	//删除一个对象
	public void remove() {
	//暂时没有使用到
	}
}


public class Boss {
	public static void main(String[] args) {
		//定义一个List,存放所有的项目对象
		ArrayList<IProject> projectList = new ArrayList<IProject>();
		//增加星球大战项目
		projectList.add(new Project("星球大战项目",10,100000));
		//增加扭转时空项目
		projectList.add(new Project("扭转时空项目",100,10000000));
		//增加超人改造项目
		projectList.add(new Project("超人改造项目",10000,1000000000));
		
		//这边100个项目
		for(int i=4;i<104;i++){
			projectList.add(new Project("第"+i+"个项目",i*5,i*1000000));
		}
		//遍历一下ArrayList,把所有的数据都取出
		//for(IProject project:projectList){
		//	System.out.println(project.getProjectInfo());
		//}
		//遍历一下ArrayList,把所有的数据都取出
		IProjectIterator projectIterator = project.iterator();
		while(projectIterator.hasNext()){
			IProject p = (IProject)projectIterator.next();
			System.out.println(p.getProjectInfo());
		}
	}
}

=======================================================

行为类

命令模式(Command Pattern)

把一个请求或者操作封装在命令对象中,命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能
在这里插入图片描述

在这里插入图片描述


解释器模式(Interptreter Pattern)

给定一种语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子
在这里插入图片描述


责任链模式(Chain of Responsibility)

使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条线,并沿着这条链传递该请求,直到有对象处理它为止
在这里插入图片描述

在这里插入图片描述
使用场景:

  • 多条件流程判断,权限控制
  • ERP系统流程审批,总经理、人事经理、项目经理
  • Java过滤器的底层实现Filter

案例1

public abstract class Approver{ //审批人
	protected String name;
	protected Approver nextApprover;//更高级别的审批人

	public Approver(String name) {
         this.name = name;
    }
    
    protected Approver setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
        return this.nextApprover;// 返回下个审批人,链式编程。
    }

	public abstract void approve(int amount);// 抽象审批方法由具体审批人子类实现
}

/**
	员工、经理、CEO各个角色
**/
public class Staff extends Approver {
    public Staff(String name) {
        super(name);
    }
    @Override
    public void approve(int amount) {
        if (amount <= 1000) {
            System.out.println("审批通过。【员工:" + name + "】");
        } else {
            System.out.println("无权审批,升级处理。【员工:" + name + "】");
            this.nextApprover.approve(amount);
        }
    }

}
public class Manager extends Approver {

    public Manager(String name) {
        super(name);
    }

    @Override
    public void approve(int amount) {
        if (amount <= 5000) {
            System.out.println("审批通过。【经理:" + name + "】");
        } else {
            System.out.println("无权审批,升级处理。【经理:" + name + "】");
            this.nextApprover.approve(amount);
        }
   }

}
public class CEO extends Approver {

    public CEO(String name) {
        super(name);
    }

    @Override
    public void approve(int amount) {
        if (amount <= 10000) {
            System.out.println("审批通过。【CEO:" + name + "】");
        } else {
            System.out.println("驳回申请。【CEO:" + name + "】");
        }
    }

}

/**
	客户端
*/
public class Client {
    public static void main(String[] args) {
        Approver flightJohn = new Staff("张飞");
        flightJohn.setNextApprover(new Manager("关羽")).setNextApprover(new CEO("刘备"));

        //高层接触不到也没必要接触,直接找员工张飞审批。
        flightJohn.approve(1000);
        /***********************
        审批通过。【员工:张飞】
        ***********************/

        flightJohn.approve(4000);
        /***********************
        无权审批,升级处理。【员工:张飞】
        审批通过。【经理:关羽】
        ***********************/

        flightJohn.approve(9000);
       /***********************
        无权审批,升级处理。【员工:张飞】
        无权审批,升级处理。【经理:关羽】
        审批通过。【CEO:刘备】
        ***********************/

        flightJohn.approve(88000);
        /***********************
        无权审批,升级处理。【员工:张飞】
        无权审批,升级处理。【经理:关羽】
        驳回申请。【CEO:刘备】
        ***********************/
    }
}

案例2
用户参加一个活动可以领取奖品,但是活动需要进行很多的规则校验然后才能放行,比如首先需要校验用户是否是新用户、今日参与人数是否有限额、全场参与人数是否有限额等等。设定的规则都通过后,才能让用户领走奖品

//定义流程上节点的基类
public abstract class RuleHandler{
	protected RuleHandler successor;//后继节点
	
	public abstract void apply(Context context);
	
	public void setSuccessor(RuleHandler successor){
		this.successor = successor;
	}
	public RuleHandler getSuccessor(){
		return successor;
	}
}

//流程实现1,检查用户是否式新用户
public class NewUserRuleHandler extends RuleHandler{
	public void apply(Context conttext){
		if(context.isNewUser()){
			if(this.getSuccessor()!=null){
				this.getSuccessor().apply(context);
			}
		}else{
			throw new RuntimeException("该活动仅限于新用户参与");
		}
	}
}

//流程实现2,检查用户所在地区是否可以参与
public class LocationRuleHandler extends RuleHandler{
	public void apply(Context context){
		boolean allowed = activityService.isSupportedLocation(context.getLocation);
		if(allowed){
			if(this.getSuccessor()!=null){
				this.getSuccessof().apply(context);
			}
		}else{
			throw new RuntimeException("非常抱歉,您所在的地区无法参与本次活动");
		}
	}
}

//流程实现3,检查奖品是否领完
public class LimitRuleHandler extends RuleHandler{
	public void apply(Context context){
		int remainedTime = activityService.queryRemainedTimes(context);//查询剩余奖品
		if(remainedTimes > 0){
			if(this.getSuccessof()!=null){
				this.getSuccessor().apply(userInfo);
			}
		}throw new RuntimeException("您来的太晚了,奖品已经被领完");
	}
}

//客户端
public static void main(String[] args){
	RuleHandler newUserHandler = new NewUserRuleHandler();
	RuleHandler locaitonHandler = new LocationRuleHandler();
	RuleHandler limitHandler = new LimitRuleHandler();

	//假设本次活动仅校验地区和奖品数量,不校验新老用户
	locationHandler.setSuccessor(limitHandler);
	locationHandler.apply(context);
}

责任链工厂的改造

将关系维护到配置文件中或者一个枚举中
在这里插入图片描述

public enum GatewayEnum{
	
	API_HANDLER(new GatewayEntity(1, "api接口限流", 
						"cn.dgut.design.chain_of_responsibility.GateWay.impl.ApiLimitGatewayHandler", null, 2)),
    BLACKLIST_HANDLER(new GatewayEntity(2, "黑名单拦截",
    					"cn.dgut.design.chain_of_responsibility.GateWay.impl.BlacklistGatewayHandler", 1, 3)),
    SESSION_HANDLER(new GatewayEntity(3, "用户会话拦截",
    					"cn.dgut.design.chain_of_responsibility.GateWay.impl.SessionGatewayHandler", 2, null)),
    ;

	GatewayEntity gatewayEntity;

    public GatewayEntity getGatewayEntity() {
        return gatewayEntity;
    }

    GatewayEnum(GatewayEntity gatewayEntity) {
        this.gatewayEntity = gatewayEntity;
    }
}
public class GatewayEntity{
	
	private String name;

    private String conference;

    private Integer handlerId;

    private Integer preHandlerId;

    private Integer nextHandlerId;
}
public interface GatewayDao{
	
	/**
     * 根据 handlerId 获取配置项
     * @param handlerId
     * @return
     */
    GatewayEntity getGatewayEntity(Integer handlerId);

    /**
     * 获取第一个处理者
     * @return
     */
    GatewayEntity getFirstGatewayEntity();
}
public class GatewayImpl implements GatewayDao {

    /**
     * 初始化,将枚举中配置的handler初始化到map中,方便获取
     */
    private static Map<Integer, GatewayEntity> gatewayEntityMap = new HashMap<>();

    static {
        GatewayEnum[] values = GatewayEnum.values();
        for (GatewayEnum value : values) {
            GatewayEntity gatewayEntity = value.getGatewayEntity();
            gatewayEntityMap.put(gatewayEntity.getHandlerId(), gatewayEntity);
        }
    }

    @Override
    public GatewayEntity getGatewayEntity(Integer handlerId) {
        return gatewayEntityMap.get(handlerId);
    }

    @Override
    public GatewayEntity getFirstGatewayEntity() {
        for (Map.Entry<Integer, GatewayEntity> entry : gatewayEntityMap.entrySet()) {
            GatewayEntity value = entry.getValue();
            //  没有上一个handler的就是第一个
            if (value.getPreHandlerId() == null) {
                return value;
            }
        }
        return null;
    }
}
public class GatewayHandlerEnumFactory {

    private static GatewayDao gatewayDao = new GatewayImpl();

    // 提供静态方法,获取第一个handler
    public static GatewayHandler getFirstGatewayHandler() {

        GatewayEntity firstGatewayEntity = gatewayDao.getFirstGatewayEntity();
        GatewayHandler firstGatewayHandler = newGatewayHandler(firstGatewayEntity);
        if (firstGatewayHandler == null) {
            return null;
        }

        GatewayEntity tempGatewayEntity = firstGatewayEntity;
        Integer nextHandlerId = null;
        GatewayHandler tempGatewayHandler = firstGatewayHandler;
        // 迭代遍历所有handler,以及将它们链接起来
        while ((nextHandlerId = tempGatewayEntity.getNextHandlerId()) != null) {
            GatewayEntity gatewayEntity = gatewayDao.getGatewayEntity(nextHandlerId);
            GatewayHandler gatewayHandler = newGatewayHandler(gatewayEntity);
            tempGatewayHandler.setNext(gatewayHandler);
            tempGatewayHandler = gatewayHandler;
            tempGatewayEntity = gatewayEntity;
        }
    // 返回第一个handler
        return firstGatewayHandler;
    }

    /**
     * 反射实体化具体的处理者
     * @param firstGatewayEntity
     * @return
     */
    private static GatewayHandler newGatewayHandler(GatewayEntity firstGatewayEntity) {
        // 获取全限定类名
        String className = firstGatewayEntity.getConference(); 
        try {
            // 根据全限定类名,加载并初始化该类,即会初始化该类的静态段
            Class<?> clazz = Class.forName(className);
            return (GatewayHandler) clazz.newInstance();
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
        return null;
    }
}

public class GetewayClient {
    public static void main(String[] args) {
        GetewayHandler firstGetewayHandler = GetewayHandlerEnumFactory.getFirstGetewayHandler();
        firstGetewayHandler.service();
    }
}

观察者模式(Observer Pattern)

又名发布-订阅(Publish/Subscribe)模式
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖它的对象都会得到通知并被自动更新
在这里插入图片描述

在这里插入图片描述

/**
	主题:
	注册观察者
	通知观察者们改变状态
*/
public class Subject {
    private List<Observer> observers = new ArrayList<Observer>();
    private int state;
    public int getState() {
        return state;
    }
    public void setState(int state) {
        this.state = state;
        // 数据已变更,通知观察者们
        notifyAllObservers();
    }
    // 注册观察者
    public void attach(Observer observer) {
        observers.add(observer);
    }
    // 通知观察者们
    public void notifyAllObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }
}

/**
	观察者及其实现类
*/
public abstract class Observer {
    protected Subject subject;
    public abstract void update();
}
public class BinaryObserver extends Observer {
    // 在构造方法中进行订阅主题
    public BinaryObserver(Subject subject) {
        this.subject = subject;
        // 通常在构造方法中将 this 发布出去的操作一定要小心
        this.subject.attach(this);
    }
    // 该方法由主题类在数据变更的时候进行调用
    @Override
    public void update() {
        String result = Integer.toBinaryString(subject.getState());
        System.out.println("订阅的数据发生变化,新的数据处理为二进制值为:" + result);
    }
}

public class HexaObserver extends Observer {
    public HexaObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }
    @Override
    public void update() {
        String result = Integer.toHexString(subject.getState()).toUpperCase();
        System.out.println("订阅的数据发生变化,新的数据处理为十六进制值为:" + result);
    }
}

public static void main(String[] args) {
    // 先定义一个主题
    Subject subject1 = new Subject();
    // 定义观察者
    new BinaryObserver(subject1);
    new HexaObserver(subject1);

    // 模拟数据变更,这个时候,观察者们的 update 方法将会被调用
    subject.setState(11);
}

案例2

/**
	被观察者接口
*/
public interface IHanFeiZi {
	//韩非子也是人,也要吃早饭的
	public void haveBreakfast();
	//韩非之也是人,是人就要娱乐活动
	public void haveFun();
}

public class HanFeiZi implements IHanFeiZi{

	//把李斯声明出来
	private ILiSi liSi =new LiSi();
	
	//韩非子是否在吃饭,作为监控的判断标准
	private boolean isHavingBreakfast = false;
	//韩非子是否在娱乐
	private boolean isHavingFun = false;
	
	//韩非子要吃饭了
	public void haveBreakfast(){
		System.out.println("韩非子:开始吃饭了...");
		this.liSi.update("韩非子在吃饭");
	}
	//韩非子开始娱乐了
	public void haveFun(){
		System.out.println("韩非子:开始娱乐了...");
		this.liSi.update("韩非子在娱乐");
	}
	//以下是bean的基本方法,getter/setter,不多说
	public boolean isHavingBreakfast() {
		return isHavingBreakfast;
	}
	public void setHavingBreakfast(boolean isHavingBreakfast) {
		this.isHavingBreakfast = isHavingBreakfast;
	}
	public boolean isHavingFun() {
		return isHavingFun;
	}
	public void setHavingFun(boolean isHavingFun) {
		this.isHavingFun = isHavingFun;
	}
}

/**
	抽象观察者
*/
public interface ILiSi {
	//一发现别人有动静,自己也要行动起来
	public void update(String context);
}
public class LiSi implements ILiSi{
	//首先李斯是个观察者,一旦韩非子有活动,他就知道,他就要向老板汇报
	public void update(String str){
		System.out.println("李斯:观察到韩非子活动,开始向老板汇报了...");
		this.reportToQinShiHuang(str);
		System.out.println("李斯:汇报完毕...\n");
	}
	//汇报给秦始皇
	private void reportToQinShiHuang(String reportContext){
		System.out.println("李斯:报告,秦老板!韩非子有活动了--->"+reportContext);
	}
}

/**
	间谍
*/
class Spy extends Thread {
    private HanFeiZi hanFeiZi;
    private LiSi liSi;
    private String type;

    //通过构造函数传递参数,我要监控的是谁,谁来监控,要监控什么
    public Spy(HanFeiZi _hanFeiZi, LiSi _liSi, String _type) {
        this.hanFeiZi = _hanFeiZi;
        this.liSi = _liSi;
        this.type = _type;
    }

    @Override
    public void run() {
        while (true) {
            if (this.type.equals("breakfast")) { //监控是否在吃早餐
                                                 //如果发现韩非子在吃饭,就通知李斯

                if (this.hanFeiZi.isHavingBreakfast()) {
                    this.liSi.update("韩非子在吃饭");
                    //重置状态,继续监控
                    this.hanFeiZi.setHavingBreakfast(false);
                }
            } else { //监控是否在娱乐

                if (this.hanFeiZi.isHavingFun()) {
                    this.liSi.update("韩非子在娱乐");
                    this.hanFeiZi.setHavingFun(false);
                }
            }
        }
    }
}

public class Client {
	public static void main(String[] args) throws InterruptedException {
		//定义出韩非子
		HanFeiZi hanFeiZi = new HanFeiZi();
		//然后我们看看韩非子在干什么
		hanFeiZi.haveBreakfast();
		//韩非子娱乐了
		hanFeiZi.haveFun();
	}
}

案例3
观察者订阅自己关心的主题,主题有数据变化后通知观察者们
观察者模式往往用消息中间件来实现

public class Subject{
	private List<Observer> observers = new ArrayList<Observer>();
	private int state;
	
	public int getState(){
		return state;
	}
	public void setState(int state){
		this.state = state;
		//数据已变更,通知观察者们
		notifyAllObservers();
	}

	//注册观察者们
	public void attach(Observer observer){
		observers.add(observer);
	}
	//通知观察者们
	public void notifyAllObservers(){
		for(Observer observer:observers){
			observer.update();
		}
	}
	
}
//定义观察者接口
public abstract class Observer{
	protected Subject subject;
	public abstract void update();
}

//观察者具体实现
public class BinaryObserver extends Observer{
	public BinaryObserver(Subject subject){
		this.subject = subject;
		this.subject.attach(this);
	}
	@Override
	public void update(){
		String result = Integer.toBinaryString(subject.getState());
		System.out.println("订阅的数据发生变化,新的数据处理为二进制的值为:"+result);
	}
}

//观察者具体实现
public class HexaObserver extends Observer{
	public HexaObserver(Subject subject){
		this.subject = subject;
		this.subject.attach(this);
	}
	@Override
	public void update(){
		String result = Integer.toHexString(subject.getState()).toUpperCase();
		System.out.println("订阅的数据发生变化,新的数据处理为二进制的值为:"+result);
	}
}
//客户端
public static void main(){
	Subject subject = new Subject();

	new BinaryObserver(subject);
	new HexaObserver(subject);

	subject.setState(11);
}

中介者模式(Mediator Pattern)

用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用。从而使其耦合松散,而且可以独立地改变它们之间的交互。
在这里插入图片描述

在这里插入图片描述

public class User {
    private String name;//名字

    private ChatRoom chatRoom;//聊天室引用

    public User(String name) {
        this.name = name;//初始化必须起名字
    }

    public String getName() {
        return this.name;
    }

    public void login(ChatRoom chatRoom) {//用户登陆
        chatRoom.connect(this);//调用聊天室连接方法
        this.chatRoom = chatRoom;//注入聊天室引用
    }

    public void talk(String msg) {//用户发言
        chatRoom.sendMsg(this, msg);//给聊天室发消息
    }

    public void listen(User fromWhom, String msg) {//且听风吟
        System.out.print("【"+this.name+"的对话框】");
        System.out.println(fromWhom.getName() + " 说: " + msg);
    }
}

public class ChatRoom {
    private String name;//聊天室命名

    public ChatRoom(String name) {
        this.name = name;//初始化必须命名聊天室
    }

    List<User> users = new ArrayList<>();//聊天室里的用户们
 
    public void connect(User user) {
        this.users.add(user);//用户进入聊天室加入列表。
        System.out.print("欢迎【");
        System.out.print(user.getName());
        System.out.println("】加入聊天室【" + this.name + "】");
    }

    public void sendMsg(User fromWhom, String msg) {
        // 循环所有用户,只发消息给非发送方fromWhom。
        users.stream()
        .filter(user -> !user.equals(fromWhom))//过滤掉发送方fromWhom  Java8的流和Lambda表达式进行过滤
        .forEach(toWhom -> toWhom.listen(fromWhom, msg));//发送消息给剩下的所有人
    }
}

备忘录模式(Memento Pattern)

在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态
在这里插入图片描述

在这里插入图片描述
案例1

/**
	备忘录:用于备忘文章内容
*/
public class History {
    private String body;
    public History(String body){
        this.body = body;
    }
    public String getBody() {
        return body;
    }
}

/**
	文档:
*/
public class Doc {
    private String title;//文章名字
    private String body;//文章内容

    public Doc(String title){//新建文档先命名
        this.title = title;
        this.body = "";
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }
	
	//创建历史记录
    public History createHistory() {
        return new History(body);
    }
	//恢复历史记录
    public void restoreHistory(History history){
        this.body = history.getBody();
    }
}

/**
	
*/
public class Editor {
    private Doc doc;
    private List<History> historyRecords;// 历史记录列表
    private int historyPosition = -1;// 历史记录当前位置

    public Editor(Doc doc) {
        System.out.println("<<<打开文档" + doc.getTitle());
        this.doc = doc; // 注入文档
        historyRecords = new ArrayList<>();// 初始化历史记录
        backup();// 保存一份历史记录
        show();//显示内容
    }

    public void append(String txt) {
        System.out.println("<<<插入操作");
        doc.setBody(doc.getBody() + txt);
        backup();//操作完成后保存历史记录
        show();
    }

    public void save(){
        System.out.println("<<<存盘操作");
    }

    public void delete(){
        System.out.println("<<<删除操作");
        doc.setBody("");
        backup();//操作完成后保存历史记录
        show();
    }

    private void backup() {
        historyRecords.add(doc.createHistory());
        historyPosition++;
    }

    private void show() {// 显示当前文本内容
        System.out.println(doc.getBody());
        System.out.println("文章结束>>>\n");
    }

    public void undo() {// 撤销操作:如按下Ctr+Z,回到过去。
        System.out.println(">>>撤销操作");
        if (historyPosition == 0) {
            return;//到头了,不能再撤销了。
        }
        historyPosition--;//历史记录位置回滚一笔
        History history = historyRecords.get(historyPosition);
        doc.restoreHistory(history);//取出历史记录并恢复至文档
        show();
    }

    // public void redo(); 省略实现代码
}

//客户端
public class Author {
    public static void main(String[] args) {
        Editor editor = new Editor(new Doc("《AI的觉醒》"));
        /*
        <<<打开文档《AI的觉醒》

        文章结束>>>
        */
        editor.append("第一章 混沌初开");
        /*
        <<<插入操作
        第一章 混沌初开
        文章结束>>>
        */
        editor.append("\n  正文2000字……");
        /*
        <<<插入操作
        第一章 混沌初开
          正文2000字……
        文章结束>>>
        */
        editor.append("\n第二章 荒漠之花\n  正文3000字……");
        /*
        <<<插入操作
        第一章 混沌初开
          正文2000字……
        第二章 荒漠之花
          正文3000字……
        文章结束>>>
        */
        editor.delete();
        /*
        <<<删除操作

        文章结束>>> 
        */

        //吃下后悔药,我的世界又完整了。
        editor.undo();
        /*
        >>>撤销操作
        第一章 混沌初开
          正文2000字……
        第二章 荒漠之花
          正文3000字……
        文章结束>>>
        */
    }
}

案例2

public class Boy {
	//男孩的状态
	private String state = "";
	//认识女孩子后状态肯定改变,比如心情、手中的花等
	public void changeState(){
		this.state = "心情可能很不好";
	}
	public String getState() {
		return state;
	}
	public void setState(String state) {
	this.state = state;
	}
	//保留一个备份(返回备忘录的对象)
	public Memento createMemento(){
		return new Memento(this.state);
	}
	//恢复一个备份
	public void restoreMemento(Memento _memento){
		this.setState(_memento.getState());
	}
}

/**
	备忘录
*/
public class Memento {
	//男孩的状态
	private String state = "";
	//通过构造函数传递状态信息
	public Memento(String _state){
		this.state = _state;
	}
	public String getState() {
		return state;
	}
	public void setState(String state) {
		this.state = state;
	}
}

public class Client {
	public static void main(String[] args) {
		//声明出主角
		Boy boy = new Boy();
		//初始化当前状态
		boy.setState("心情很棒!");
		System.out.println("=====男孩现在的状态======");
		System.out.println(boy.getState());
		//需要记录下当前状态呀
		Memento mem = boy.createMemento();
		//男孩去追女孩,状态改变
		boy.changeState();
		System.out.println("\n=====男孩追女孩子后的状态======");
		System.out.println(boy.getState());
		//追女孩失败,恢复原状
		boy.restoreMemento(mem);
		System.out.println("\n=====男孩恢复后的状态======");
		System.out.println(boy.getState());
	}
}

状态模式(State Pattern)

允许一个对象在其内部状态改变时改变它的行为
在这里插入图片描述

在这里插入图片描述

public interface State {
    public void doAction(Context context);
}

//定义减库存状态
public class DeductState implements State {

    public void doAction(Context context) {
        System.out.println("商品卖出,准备减库存");
        context.setState(this);

        //... 执行减库存的具体操作
    }

    public String toString() {
        return "Deduct State";
    }
}

//定义补库存状态
public class RevertState implements State {

    public void doAction(Context context) {
        System.out.println("给此商品补库存");
        context.setState(this);

        //... 执行加库存的具体操作
    }

    public String toString() {
        return "Revert State";
    }
}

public class Context {
    private State state;
    private String name;
    public Context(String name) {
        this.name = name;
    }

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

public static void main(String[] args) {
        // 我们需要操作的是 iPhone X
        Context context = new Context("iPhone X");

        // 看看怎么进行补库存操作
        State revertState = new RevertState();
        revertState.doAction(context);

        // 同样的,减库存操作也非常简单
        State deductState = new DeductState();
        deductState.doAction(context);

        // 如果需要我们可以获取当前的状态
        // context.getState().toString();
        }

策略模式(Strategy Pattern)

定义一组算法,将每个算法都封装起来,并且使它们之间可以互换
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

案例1

/**
	算法标准
*/
public interface Strategy {
    public int calculate(int a, int b);//操作数,被操作数
}

/**
	具体的算法实现:加、减
*/
public class Addition implements Strategy{//实现算法接口
    @Override
    public int calculate(int a, int b) {//加数与被加数
        return a + b;//这里我们做加法运算
    }
}
public class Subtraction implements Strategy{//实现算法接口
    @Override
    public int calculate(int a, int b) {//减数与被减数
        return a - b;//这里我们做减法运算
    }
}

/**
	计算器
*/
public class Calculator {
    private Strategy strategy;//拥有某种算法策略

    public void setStrategy(Strategy strategy) {//接入算法策略
        this.strategy = strategy;
    }

    public int getResult(int a, int b){
        return this.strategy.calculate(a, b);//返回具体策略的结果
    }
}

public class Client {
    public static void main(String[] args) {
        Calculator calculator = new Calculator();//实例化计算器
        calculator.setStrategy(new Addition());//接入加法实现
        int result = calculator.getResult(1, 1);//计算!
        System.out.println(result);//得到的是加法结果2

        calculator.setStrategy(new Subtraction());//再次接入减法实现
        result = calculator.getResult(1, 1);//计算!
        System.out.println(result);//得到的是减法结果0

    }
}

案例2

public interface IStrategy {
	//每个锦囊妙计都是一个可执行的算法
	public void operate();
}

public class BackDoor implements IStrategy {
	public void operate() {
		System.out.println("找乔国老帮忙,让吴国太给孙权施加压力");
	}
}
public class GivenGreenLight implements IStrategy {
	public void operate() {
		System.out.println("求吴国太开绿灯,放行!");
	}
}
public class BlockEnemy implements IStrategy {
	public void operate() {
		System.out.println("孙夫人断后,挡住追兵");
	}
}

public class Context {
	//构造函数,你要使用哪个妙计
	private IStrategy straegy;
	public Context(IStrategy strategy){
		this.straegy = strategy;
	}
	//使用计谋了,看我出招了
	public void operate(){
		this.straegy.operate();
	}
}

案例3

public interface MyPredicate<T>{
	public boolean test(T t);
}

//获取年龄大于35
public class FilterEmployeeByAge implements  MyPredicate<Employee>{
	@Override
	public boolean test(Employee t){
		return t.getAge() >= 35;
	}
}
//获取工资大于5000
public class FilterEmployeeBySalary implements  MyPredicate<Employee>{
	@Override
	public boolean test(Employee t){
		return t.getSalary() >= 5000;
	}
}

// 根据不同的策略实现不同的查询条件
public List<Employee> filterEmployee(List<Employee> list, MyPredicate<Employee> mp){
	List<Employee> emps = new ArrayList<>();

	for(Employee employee : list){
		if(mp.test(empoyee)){
			emps.add(employee)
		}
	}
	return emps;
}

//以上做法可以采用匿名内部类(Lambda表达式)
public void test(){
	List<Employee> list1 = filterEmployee(employees,new FilterEmployeeByAge());
	
	List<Employee> list2 = filterEmployee(employees,new FilterEmployeeBySalary());
}

SpringBoot+策略模式

public interface CalculationStrategy{
	
	int operate(int num1,int num2);
}
@Component("add")
class AddCalculationStrategyImpl implements CalculationStrategy{
	
	@Override
	public int operate(int num1,int num2){
		return num1 + num2;
	}
}

@Component("Division")
class DivisionStrategyImpl implements CalculationStrategy{
	
	@Override
	public int operate(int num1,int num2){
		return num1 / num2;
	}
}

@Component("multiple")
class MultiplicationStrategyImpl implements CalculationStrategy{
	
	@Override
	public int operate(int num1,int num2){
		return num1 * num2;
	}
}

@Component("substract")
class SubtractionStrategyImpl implements CalculationStrategy{
	
	@Override
	public int operate(int num1,int num2){
		return num1 - num2;
	}
}

/**
 * 如果Component注解中不写标识会默认加载驼峰类名:testStrategyImpl
 */
@Component
class TestStrategyImpl implements CalculationStrategy {

    @Override
    public int operate(int num1, int num2) {
        return num1 - num2;
    }
}
/**
	策略上下文
*/
@Component
public class CalculationFactory

	
	/**
     *  把策略角色(类型)key,和参数value放到Map中
     *  key就是beanName(具体策略实现类中@Component的名字),value就是接口(具体的实现类)
     *  Maps是guava下的封装类型,实则是静态的创建了一个HashMap的对象,Maps可以根据key去获取value对象
     */
	public final Map<String,CalculationStrategy> calculationStrategyMap = Maps.newHashMapWithExpectedSize(4);

	public CalculationFactory(Map<String, CalculationStrategy> strategyMap) {
        this.calculationStrategyMap.clear();
        this.calculationStrategyMap.putAll(strategyMap);
    }

	//可以使用@Getter注解代替,这样写方便读者理解在Service层调用Context执行策略
    public Map<String, CalculationStrategy> getCalculationStrategyMap() {
        return calculationStrategyMap;
    }
}
//路由接口实现
@Service
public class CalculationService {

    @Autowired
    private CalculationFactory calculationFactory;

    public int operateByStrategy(String strategy, int num1, int num2) {
        // 获取入参,根据不同的参数类型去执行不同的策略,Context的get方法是在这个地方用到的,operate方法就是一开始定义的策略接口
        //calculationFactory.getCalculationStrategyMap().get(strategy)这里可能会出现空,所以要做一个容错处理
        return calculationFactory.getCalculationStrategyMap().get(strategy).operate(num1, num2);
    }
}
@RestController
@RequestMapping("/strategy")
public class TestStrategyController {
    @Autowired
    private CalculationService calculationService;

    @GetMapping("/test/{operation}/{num1}/{num2}")
    public int testCalculation(@PathVariable String operation,@PathVariable  int num1, @PathVariable int num2) {
        // 省略参数判空
        return calculationService.operateByStrategy(operation, num1, num2);
    }
}

模板方法模式(Template Method Pattern)

在这里插入图片描述

在这里插入图片描述

案例1

//以抽象类的方式代替接口,同时也有一些实体方法,以供子类直接继承
public abstract class Mamal{ 
	protected final void feedMilk(){
		if(female){//雌性哺乳动物可以喂奶
			System.out.println("喂奶");
		}else{
			System.out.println("不可以喂奶");
		}
	}
		
	public abstract void move();//该抽象方法由子类重写,相当于接口规范
}

/**
`看到子类的各路实现都是自己独有的行为方式,而喂奶那个行为是不需要自己实现的,它是属于抽象哺乳类的共有行为,哺乳子类不能进行任何干涉。这便是接口与抽象的最大区别了,接口是虚的,抽象类可以有虚有实,接口不在乎实现类是什么,抽象类会延续其基因给子类
*/
public class Human extends Mammal{
	@Override
    public void move() {
        System.out.println("两条腿走路……");
    }
}

案例2

public abstract class PM {
    protected abstract void analyze();//需求分析
    protected abstract void design();//设计
    protected abstract void develop();//开发
    protected abstract boolean test();//测试
    protected abstract void release();//发布

    protected final void kickoff(){ //用final声明此方法子类不可以重写,只能乖乖的继承下去用。至于其他的抽象方法,子类可以自由发挥
        analyze();
        design();
        develop();
        test();
        release();
    }
}

//子类只需要实现抽象方法,不用实现固有的模板方法kickoff()
public class AutoTestPM extends PM{
    @Override
    protected void analyze() {
        System.out.println("进行业务沟通,需求分析");     
    }

    //design();develop();test();release();实现省略
}

案例3

public abstract class AbstractTemplate{
	//模板方法
	public void templateMethod(){
		init();
		apply();
		end();//作为钩子方法
	}
	protected void init(){
		System.out.println("init抽象层已经实现,子类可以选择复写");
	}

	//留给子类实现
	protected abstract void apply();
	
	protected void end(){
	}
}

public class ConcreteTemplate extends AbstractTemplate{
	public void apply(){
		System.out.pritln("子类实现抽象方法apply");
	}
	public void end(){
		System.out.pritln("把method3当作钩子方法来使用,使用的时候复写即可");
	}
}

//客户端调用
public static void main(String[] args){
	AbstractTemplate t = new ConcreteTemplate();
	t.templateMethod();
}

访问者模式(Visitor Pattern)

封装一些作用于某种数据结构中的各元素的操作,它可以不改变数据结构的前提下定义作用于这些元素的新的操作
在这里插入图片描述

在这里插入图片描述

/**
	访问者接口及其实现类
*/
public interface IVisitor {
	//首先,定义我可以访问普通员工
	public void visit(CommonEmployee commonEmployee);
	//其次,定义我还可以访问部门经理
	public void visit(Manager manager);
}

public class Visitor implements IVisitor {
    //访问普通员工,打印出报表
    public void visit(CommonEmployee commonEmployee) {
        System.out.println(this.getCommonEmployee(commonEmployee));
    }

    //访问部门经理,打印出报表
    public void visit(Manager manager) {
        System.out.println(this.getManagerInfo(manager));
    }

    //组装出基本信息
    private String getBasicInfo(Employee employee) {
        String info = "姓名:" + employee.getName() + "\t";
        info = info + "性别:" +
            ((employee.getSex() == Employee.FEMALE) ? "女" : "男") + "\t";
        info = info + "薪水:" + employee.getSalary() + "\t";

        return info;
    }

    //组装出部门经理的信息
    private String getManagerInfo(Manager manager) {
        String basicInfo = this.getBasicInfo(manager);
        String otherInfo = "业绩:" + manager.getPerformance() + "\t";

        return basicInfo + otherInfo;
    }

    //组装出普通员工信息
    private String getCommonEmployee(CommonEmployee commonEmployee) {
        String basicInfo = this.getBasicInfo(commonEmployee);
        String otherInfo = "工作:" + commonEmployee.getJob() + "\t";

        return basicInfo + otherInfo;
    }
}


public abstract class Employee {
    public final static int MALE = 0; //0代表是男性
    public final static int FEMALE = 1; //1代表是女性
                                        //甭管是谁,都有工资
    private String name;

    //只要是员工那就有薪水
    private int salary;

    //性别很重要
    private int sex;

    //以下是简单的getter/setter
    public String getName() {
        return name;
    }

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

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    public int getSex() {
        return sex;
    }

    public void setSex(int sex) {
        this.sex = sex;
    }

    //我允许一个访问者访问
    public abstract void accept(IVisitor visitor);
}

//普通员工
public class CommonEmployee extends Employee {
    //工作内容,这非常重要,以后的职业规划就是靠它了
    private String job;

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    //我允许访问者访问
    @Override
    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }
}
//管理层员工
public class Manager extends Employee {
    //这类人物的职责非常明确:业绩
    private String performance;

    public String getPerformance() {
        return performance;
    }

    public void setPerformance(String performance) {
        this.performance = performance;
    }

    //部门经理允许访问者访问
    @Override
    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }
}

public class Client {
    public static void main(String[] args) {
        for (Employee emp : mockEmployee()) {
            emp.accept(new Visitor());
        }
    }

    //模拟出公司的人员情况,我们可以想象这个数据是通过持久层传递过来的
    public static List<Employee> mockEmployee() {
        List<Employee> empList = new ArrayList<Employee>();

        //产生张三这个员工
        CommonEmployee zhangSan = new CommonEmployee();
        zhangSan.setJob("编写Java程序,绝对的蓝领、苦工加搬运工");
        zhangSan.setName("张三");
        zhangSan.setSalary(1800);
        zhangSan.setSex(Employee.MALE);
        empList.add(zhangSan);

        //产生李四这个员工
        CommonEmployee liSi = new CommonEmployee();
        liSi.setJob("页面美工,审美素质太不流行了!");
        liSi.setName("李四");
        liSi.setSalary(1900);
        liSi.setSex(Employee.FEMALE);
        empList.add(liSi);

        //再产生一个经理
        Manager wangWu = new Manager();
        wangWu.setName("王五");
        wangWu.setPerformance("基本上是负值,但是我会拍马屁呀");
        wangWu.setSalary(18750);
        wangWu.setSex(Employee.MALE);
        empList.add(wangWu);

        return empList;
    }
}

=======================================================

结构类

适配器模式(Adapter Pattern)

默认适配器模式、对象适配器模式、类适配器模式三种
在这里插入图片描述

将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
在这里插入图片描述
默认适配器:Appache commons-io包中的FileAlterationListener的例子

/**
	此接口的一大问题是抽象方法太多了,如果我们要用这个接口,意味着我们要实现每一个抽象方法,如果我们只是想要监控文件夹中的文件创建和文件删除事件,可是我们还是不得不实现所有的方法,很明显,这不是我们想要的。
*/
public interface FileAlterationListener {
    void onStart(final FileAlterationObserver observer);
    void onDirectoryCreate(final File directory);
    void onDirectoryChange(final File directory);
    void onDirectoryDelete(final File directory);
    void onFileCreate(final File file);
    void onFileChange(final File file);
    void onFileDelete(final File file);
    void onStop(final FileAlterationObserver observer);
}
/**
	我们需要下面的一个适配器,它用于实现上面的接口,但是所有的方法都是空方法,这样,我们就可以转而定义自己的类来继承下面这个类即可。
*/
public class FileAlterationListenerAdaptor implements FileAlterationListener {

    public void onStart(final FileAlterationObserver observer) {
    }

    public void onDirectoryCreate(final File directory) {
    }

    public void onDirectoryChange(final File directory) {
    }

    public void onDirectoryDelete(final File directory) {
    }

    public void onFileCreate(final File file) {
    }

    public void onFileChange(final File file) {
    }

    public void onFileDelete(final File file) {
    }

    public void onStop(final FileAlterationObserver observer) {
    }
}
/**
	定义以下类,我们仅仅需要实现我们想实现的方法就可以了:
*/
public class FileMonitor extends FileAlterationListenerAdaptor {
    public void onFileCreate(final File file) {
        // 文件创建
        doSomething();
    }

    public void onFileDelete(final File file) {
        // 文件删除
        doSomething();
    }
}

对象适配模式案例1
在这里插入图片描述
在这里插入图片描述

/**
	目标接口:三插孔标准
*/
public interface TriplePin {
    //参数分别为火线live,零线null,地线earth
    public void electrify(int l, int n, int e);
}

/**
	适配器
	适配器模式总体来说分三种:默认适配器模式、对象适配器模式、类适配器模式。

	类适配和对象适配的异同:一个采用继承,一个采用组合。类适配属于静态实现,对象适配属于组合的动态实现,对象适配需要多实例化一个对象
*/
public class Adapter implements TriplePin {

    private DualPin dualPinDevice; //两孔标准的引用

    //创建适配器地时候,需要把双插设备接入进来
    public Adapter(DualPin dualPinDevice) {
        this.dualPinDevice = dualPinDevice;
    }

    //适配器实现的是目标接口
    @Override
    public void electrify(int l, int n, int e) {
        //实际上调用了被适配设备的双插通电,地线e被丢弃了。
        dualPinDevice.electrify(l, n);
    }

}
//或者,类适配器
public class ClassAdapter extends TV implements TriplePin{
    @Override
    public void electrify(int l, int n, int e) {
        super.electrify(l, n);
    }
}


/**
	两插孔标准:电视机的两插标准
*/
public interface DualPin {
    public void electrify(int l, int n);//这里没有地线
}
//电视机实现类
public class TV implements DualPin {

    @Override//既然是两项插头,当然实现两项插标准
    public void electrify(int l, int n) {
        System.out.println("火线通电:" + l);
        System.out.println("零线通电:" + n);
    }

}

组合模式(Composite Pattern)

将对象组合成树形结构以表示“部分整体”的层次结构,使得用于对单个对象和组合对象使用具有一致性

在这里插入图片描述

在这里插入图片描述

案例1

public interface Test{
	public abstract int countTestCases();
	public abstract void run(TestResult result);
}

public class TestSuite implements Test{
	private Vector fTests = new Vector(10);
	private String fName;

	public void addTest(Test test){
		fTests.addElement(test);
	}

	public int countTestCases() { 
		 int count= 0; 
		 for (Enumeration e= tests(); e.hasMoreElements(); ) { 
			 Test test= (Test)e.nextElement(); 
			 count= count + test.countTestCases(); 
		 } 
		 return count; 
 	}

	public void run(TestResult result) { 
		 for (Enumeration e= tests(); e.hasMoreElements(); ) { 
			 if (result.shouldStop() ) 
			 	break; 
			 Test test= (Test)e.nextElement(); 
			 //关键在这个方法上面
			 runTest(test, result); 
		 } 
	 }

	public void runTest(Test test, TestResult result) { 
		 test.run(result); 
	 } 

}


案例2

public abstract class Node{
	protected String name;
	public Node(String name){
		this.name = name;
	}
	protected abstract void add(Node child);
}

public class Folder extends Node{
	private List<Node> childrenNodes = new ArrayList<>();
	public Folder(String name){
		super(name);
	}
	 @Override
    protected void add(Node child) {
        childrenNodes.add(child);//可以添加子节点。
    }
}

public class File extends Node{
    public File(String name) {
        super(name);
    }
    @Override
    protected void add(Node child) {
        System.out.println("不能添加子节点。");
    }
}

public class Client {
    public static void main(String[] args) {
        Node driveD = new Folder("D盘");

        Node doc = new Folder("文档");
        doc.add(new File("简历.doc"));
        doc.add(new File("项目介绍.ppt"));

        driveD.add(doc);

        Node music = new Folder("音乐");

        Node jay = new Folder("周杰伦");
        jay.add(new File("双截棍.mp3"));
        jay.add(new File("告白气球.mp3"));
        jay.add(new File("听妈妈的话.mp3"));

        Node jack = new Folder("张学友");
        jack.add(new File("吻别.mp3"));
        jack.add(new File("一千个伤心的理由.mp3"));

        music.add(jay);
        music.add(jack);

        driveD.add(music);
    }
}

案例3
具有层次结构的数据,使得我们对单个对象和组合对象的访问具有一致性

public class Employee{
	private String name;
	private String dept;
	private int salary;
	private List<Employee> subordinates;//下属

	public Employee(String name,String dept,int sal){
		this.name = name;
		this.dept = dept;
		this.salary = sal;
		subordinates = new ArrayList<Empleoyee>();
	}

	public void add(Employee e){
		subordinates.add(e);
	}
	public void remove(Employee e){
		subordinates.remove(e);
	}
	public List<Employee> getSubordinates(){
		return subordinates;
	}
}

代理模式(Proxy Pattern)

为其他对象提供一种代理以控制对这个对象的访问
在这里插入图片描述

在这里插入图片描述

public interface FoodService {
    Food makeChicken();
    Food makeNoodle();
}

public class FoodServiceImpl implements FoodService {
    public Food makeChicken() {
          Food f = new Chicken()
        f.setChicken("1kg");
          f.setSpicy("1g");
          f.setSalt("3g");
        return f;
    }
    public Food makeNoodle() {
        Food f = new Noodle();
        f.setNoodle("500g");
        f.setSalt("5g");
        return f;
    }
}

// 代理要表现得“就像是”真实实现类,所以需要实现 FoodService
public class FoodServiceProxy implements FoodService {

    // 内部一定要有一个真实的实现类,当然也可以通过构造方法注入
    private FoodService foodService = new FoodServiceImpl();

    public Food makeChicken() {
        System.out.println("我们马上要开始制作鸡肉了");

        // 如果我们定义这句为核心代码的话,那么,核心代码是真实实现类做的,
        // 代理只是在核心代码前后做些“无足轻重”的事情
        Food food = foodService.makeChicken();

        System.out.println("鸡肉制作完成啦,加点胡椒粉"); // 增强
          food.addCondiment("pepper");

        return food;
    }
    public Food makeNoodle() {
        System.out.println("准备制作拉面~");
        Food food = foodService.makeNoodle();
        System.out.println("制作完成啦")
        return food;
    }
}

在这里插入图片描述


桥梁模式(Bridge Pattern)

将抽象和实现解耦,使得两者可以独立的变化
在这里插入图片描述

在这里插入图片描述

/**
	接口 及其实现类
*/
public interface DrawAPI {  
	 public void draw(int radius, int x, int y);
}
public class RedPen implements DrawAPI {
    @Override
    public void draw(int radius, int x, int y) {
        System.out.println("用红色笔画图,radius:" + radius + ", x:" + x + ", y:" + y);
    }
}
public class GreenPen implements DrawAPI {
    @Override
    public void draw(int radius, int x, int y) {
        System.out.println("用绿色笔画图,radius:" + radius + ", x:" + x + ", y:" + y);
    }
}
public class BluePen implements DrawAPI {
    @Override
    public void draw(int radius, int x, int y) {
        System.out.println("用蓝色笔画图,radius:" + radius + ", x:" + x + ", y:" + y);
    }
}

/**
	形状的抽象类及其实现类
*/
public abstract class Shape {
    protected DrawAPI drawAPI;
    protected Shape(DrawAPI drawAPI) {
        this.drawAPI = drawAPI;
    }
    public abstract void draw();
}
// 圆形
public class Circle extends Shape {
    private int radius;
    public Circle(int radius, DrawAPI drawAPI) {
        super(drawAPI);
        this.radius = radius;
    }
    public void draw() {
        drawAPI.draw(radius, 0, 0);
    }
}
// 长方形
public class Rectangle extends Shape {
    private int x;
    private int y;
    public Rectangle(int x, int y, DrawAPI drawAPI) {
        super(drawAPI);
        this.x = x;
        this.y = y;
    }
    public void draw() {
        drawAPI.draw(0, x, y);
    }
}

public static void main(String[] args) {
    Shape greenCircle = new Circle(10, new GreenPen());
    Shape redRectangle = new Rectangle(4, 8, new RedPen());
    greenCircle.draw();
    redRectangle.draw();
}

装饰模式(Decorator Pattern)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

装饰模式(Decorator)也叫包装器模式(Wrapper)。
动态地为对象添加一些额外的职责,就增加功能来说,它相比生成子类更为灵活
在这里插入图片描述
案例1

public interface Showable {
    public void show();//定义展示行为
}

public class Girl implements Showable{
    @Override
    public void show() {
        System.out.print("女孩的素颜");
    }
}

/**
	装饰者,化妆品
*/
public abstract class Decorator implements Showable{
    protected Showable showable;

    public Decorator(Showable showable) {
        this.showable = showable;
    }

    @Override
    public void show() {
        showable.show();//直接调用不做加任何粉饰。
    }
}

/**
	粉底类继承了化妆品类
*/
public class FoundationMakeup extends Decorator{
    public FoundationMakeup(Showable showable) {
        super(showable);//调用化妆品父类注入
    }

    @Override
    public void show() {
        System.out.print("打粉底(");
        showable.show();
        System.out.print(")");
    }
}

/**
	口红类继承化妆品
*/
public class Lipstick extends Decorator{
    public Lipstick(Showable showable) {
        super(showable);
    }

    @Override
    public void show() {
        System.out.print("涂口红(");
        showable.show();
        System.out.print(")");
    }
}

public class Client {
    public static void main(String[] args) {
        //口红包裹粉底,再包裹女友。
        Showable madeupGirl = new Lipstick(new FoundationMakeup(new Girl()));
        madeupGirl.show();
        //运行结果:涂口红(打粉底(女孩的脸庞))
    }
}

案例2

/**
	抽象成绩单
*/
public abstract class SchoolReport {
	//成绩单主要展示的就是你的成绩情况
	public abstract void report();
	//成绩单要家长签字,这个是最要命的
	public abstract void sign();
}

/**
	四年级成绩单
*/
public class FouthGradeSchoolReport extends SchoolReport {
    //我的成绩单
    public void report() {
        //成绩单的格式是这个样子的
        System.out.println("尊敬的XXX家长:");
        System.out.println(" ......");
        System.out.println(" 语文 62 数学65 体育 98 自然 63");
        System.out.println(" .......");
        System.out.println(" 家长签名: ");
    }

    //家长签名
    public void sign(String name) {
        System.out.println("家长签名为:" + name);
    }
}

/**
	装饰进行修饰成绩单
*/
public class SugarFouthGradeSchoolReport extends FouthGradeSchoolReport {
    //首先要定义你要美化的方法,先给老爸说学校最高成绩
    private void reportHighScore() {
        System.out.println("这次考试语文最高是75,数学是78,自然是80");
    }

    //在老爸看完毕成绩单后,我再汇报学校的排名情况
    private void reportSort() {
        System.out.println("我是排名第38名...");
    }

    //由于汇报的内容已经发生变更,那所以要重写父类
    @Override
    public void report() {
        this.reportHighScore(); //先说最高成绩
        super.report(); //然后老爸看成绩单
        this.reportSort(); //然后告诉老爸学习学校排名
    }
}


public class Father {
    public static void main(String[] args) {
        //把成绩单拿过来
        SchoolReport sr = new SugarFouthGradeSchoolReport();
        //看成绩单
        sr.report();

        //签名?休想!sr.sign("jordan");
    }
}

案例3
在这里插入图片描述

//定义饮料抽象基类
public abstract class Beverage{
	public abstract String getDescription();//返回描述
	public abstract double const(); //返回价格
}

//定义实现类(红茶、绿茶)
public class BlackTea extends Beverage{
	public String getDescription(){
		return "红茶";
	}
	public double const(){
		return 10;
	}
}
public class GreenTea extends Beverage{
	public String getDescription(){
		return "绿茶";
	}
	public double const(){
		return 11;
	}
}
public class BlackTea extends Beverage{
	public String getDescription(){
		return "红茶";
	}
	public double const(){
		return 10;
	}
}
//定义装饰者基类以及实现类——调料,必须继承饮料
public abstract class Condiment extends Beverage{
	
}
public class Lemon extends Condiment{ //柠檬
	private Beverage bevarage;
	public Lemon(Beverage bevarage){
		this.bevarage = bevarage;
	}
	public String getDescription(){
		return bevarage.getDescription() + ",加柠檬"
	}
	public double const(){
		return beverage.const() + 2;
	}
}

//客户端调用
public static void main(String[] args){
	Beverage beverage = new GreenTea();

	beverage = new Lemon(beverage);//加柠檬
	beverage = new Mongo(beverage);//加芒果
}

门面模式(Facade Pattern)

要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行,门面模式提供一个高层次的接口,使得子系统更易于使用
门面模式(也叫外观模式,Facade Pattern)
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

案例1

public class VegVendor {//菜贩子
    public void sell(){
        System.out.println("菜贩子卖菜。。。");
    }
}
public class GirlFriend {//女友
    public void cook(){
        System.out.println("女友烹饪。。。");
    }
}
//客户端创建多个对象
public class Me {
    public void eat() {
        System.out.println("我只会吃。。。");
    }
    public static void main(String[] args) {
        //找菜贩子买菜
        VegVendor vv = new VegVendor();
        vv.sell();

        //找女友做饭
        GirlFriend gf = new GirlFriend();
        gf.cook();

        //我只会吃
        Me me = new Me();
        me.eat();

        //谁洗碗呢?一场战场一触即发……
    }
}

/**
	厨师将以上多个对象进行整合
*/
public class Facade {
    private VegVendor vv;
    private Chef chef;
    private Waiter waiter;
    private Cleaner cleaner;

    public Facade() {
        this.vv = new VegVendor();
        //开门前就找菜贩子准备好蔬菜
        vv.sell();
        //当然还得雇佣好各类饭店服务人员
        this.chef = new Chef();
        this.waiter = new Waiter();
        this.cleaner = new Cleaner();
    }

    public void provideService(){
        //接待,入座,点菜
        waiter.order();
        //找厨师做饭
        chef.cook();
        //上菜
        waiter.serve();
        //收拾桌子,洗碗,以及其他工序……
        cleaner.clean();
        cleaner.wash();
    }
}

案例2

/**
	定义一个形状接口,实现类伪圆形和矩形
*/
public interface Shape {
   void draw();
}
public class Circle implements Shape {
    @Override
    public void draw() {
       System.out.println("Circle::draw()");
    }
}

public class Rectangle implements Shape {
    @Override
    public void draw() {
       System.out.println("Rectangle::draw()");
    }
}

/**
	定义一个门面类,进行整合
*/
public class ShapeMaker {
   private Shape circle;
   private Shape rectangle;
   private Shape square;

   public ShapeMaker() {
      circle = new Circle();
      rectangle = new Rectangle();
      square = new Square();
   }

  /**
   * 下面定义一堆方法,具体应该调用什么方法,由这个门面来决定
   */

   public void drawCircle(){
      circle.draw();
   }
   public void drawRectangle(){
      rectangle.draw();
   }
   public void drawSquare(){
      square.draw();
   }
}

public static void main(String[] args) {
  ShapeMaker shapeMaker = new ShapeMaker();

  // 客户端调用现在更加清晰了
  shapeMaker.drawCircle();
  shapeMaker.drawRectangle();
  shapeMaker.drawSquare();
}

享元模式(Flyweight Pattern)

使用共享对象可有效地支持大量的细粒度的对象
在这里插入图片描述

在这里插入图片描述

public class SignInfo {
    //报名人员的ID
    private String id;

    //考试地点
    private String location;

    //考试科目
    private String subject;

    //邮寄地址
    private String postAddress;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getPostAddress() {
        return postAddress;
    }

    public void setPostAddress(String postAddress) {
        this.postAddress = postAddress;
    }
}

public class SignInfo4Pool extends SignInfo {
	//定义一个对象池提取的KEY值
	private String key;
	//构造函数获得相同标志
	public SignInfo4Pool(String _key){
		this.key = _key;
	}
	public String getKey() {
		return key;
	}
	public void setKey(String key) {
		this.key = key;
	}
}

/**
	工厂创建对象
*/
public class SignInfoFactory {
    //池容器
    private static HashMap<String, SignInfo> pool = new HashMap<String, SignInfo>();

    //报名信息的对象工厂
    @Deprecated
    public static SignInfo() {
        return new SignInfo();
    }

    //从池中获得对象
    public static SignInfo getSignInfo(String key) {
        //设置返回对象
        SignInfo result = null;

        //池中没有该对象,则建立,并放入池中
        if (!pool.containsKey(key)) {
            System.out.println(key + "----建立对象,并放置到池中");
            result = new SignInfo4Pool(key);
            pool.put(key, result);
        } else {
            result = pool.get(key);
            System.out.println(key + "---直接从池中取得");
        }

        return result;
    }
}



public class Client {
    public static void main(String[] args) {
        //初始化对象池
        for (int i = 0; i < 4; i++) {
            String subject = "科目" + i;

            //初始化地址
            for (int j = 0; j < 30; j++) {
                String key = subject + "考试地点" + j;
                SignInfoFactory.getSignInfo(key);
            }
        }

        SignInfo signInfo = SignInfoFactory.getSignInfo("科目1考试地点1");
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值