最简单的Java设计模式

Java设计模式

标签: Java 设计模式

设计模式六大原则

  • 单一职责原则
  • 开闭原则
  • 依赖倒置原则
  • 迪米特法则
  • 接口隔离原则
  • 里氏替换原则

单一职责原则

简述:对功能进行分类,尽量实现一个类之负责一个功能。

例子:人吃饭。人 和 饭分别为类,人拥有吃的能力。

作用:编程上要使用到单一职责,做到职责分离,更大程度的达到代码复用,使系统的设计更加灵活,易维护。

开闭原则

简述:类,函数,属性对扩展开放,对修改关闭。

例子:当我们因部分原因需要对原有代码进行修改时,可能会给那些引入旧代码的部分出现错误,也可能会使我们不得不重构整个功能,并且需要原有代码进行测试,需要开闭原则来解决这种问题。

依赖倒置原则

简述:抽象不依赖细节,细节依赖于抽象,也就是面向接口编程。

例子:内存条和硬盘都是面向接口设计的,如果是面向细节的话增加内存条或硬盘可能就需要换主板了。

迪米特法则

简述:一个对象应该对其他对象尽少了解,不需要知道它内部是如何复杂实现的。调用者只需要知道他需要的方法即可。尽量减少耦合度。
耦合度越大当一个类发生改变时,对另一个类的影响也越大。

例子:使用框架时,开发者都会抽出一个类供使用者调用,而这个类像中介一样去调用其他的类。

接口隔离原则

简述:在定义接口方法的时候尽量追求简单,避免接口臃肿。

例子:在开发过程中,为了节省时间可能会将很多功能抽象成接口,这样并不对,需要合理的拆分接口的方法,另外抽取一个独立的接口,避免原有的接口臃肿导致代码难以理解。

里氏替换原则

简述:在继承类时,除了扩展新的功能外,尽量不要删除或修改对父类方法的引用,也尽量不要重载父类的方法。

例子:每个类都是Object的子类,Object中有个toString()的方法。若子类重写此方法并返回Null,这个类的下一级继承也返回Null,不同开发人员维护时考虑不到此问题,很可能导致程序崩溃。

设计模式

单例模式

单例模式即一个类只有一个实例的存在。

饿汉模式

在小明年轻时,电视机还没被普及,那时他非常想看电视,恰巧他邻居是个大土豪,买了高清蓝光4K钛合金电视,于是小明就去土豪家,然而小明的邻居都在土豪家。土豪说:我先看,我看完新闻联播了。你们再决定来看什么。
    private static TV tv = new TV(); //首先,土豪买了个电视机
    private TV(){
     }  //因为土豪的,所以是private
    public static TV getTV(){
        //土豪看困了,让下个人看。
        return tv;
    }
那个时候电视机只有一个,大家都想看,这种就叫做饿汉单例模式。

懒汉模式

后来,小明另一个邻居老王家也买了电视,老王早就过了看电视的年龄,电视放在那。
    private TV(){
     }
    private static Tv tv;
小明觉得不看太可惜了,就去老王家看,老王很大方,随便看吧
    public static TV getTV(){
     
        if(tv==null){
     
            tv = new TV();
        }
        return tv;
    }
这种想看就开电视看,随便看的模式叫懒汉模式。

双重检验锁

最近老王家买了电脑,小明天天去玩,而他表弟听说后也随风而来。当小明玩的时候,老王很仗义的告诉他表弟说电脑锁忘了,想起来告诉他。
    //所有的写(write)操作都将发生在读(read)操作之前。
    private volatile static Computer computer;
    
    public static Computer getComputer(){
      
        if(computer==null){
     
            synchronized(Computer.class){
      //保证了同一时间只能只能有一个对象访问此同步块
                if(computer==null){
     
                    computer = new Computer();
                }
            }
        }
        return computer;
    }
这就是所谓的双重检验锁。

工厂模式

在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

简单工厂模式

小明家附近有个老面馆。提供三种面条贩卖。
    //面条接口
    public interface Noodle{
     
        void desc();    //面条描述方法
    }
    
    //拉面类
    public class HandPulledNoodle implements Noodle{
     
        public void desc(){
     
            System.out.println("好吃的拉面");
        }
    }
    
    //方便面
    public class InstantNoodle implements Noodle{
     
        public void desc(){
     
            System.out.println("康师傅方便面");
        }
    }
    
    //干扣面
    public DryBuckleSurface implements Noodle{
     
        public void desc(){
     
            System.out.println("辣味十足的干扣面");
        }
    }
面馆里有个拉面师傅,告诉他你想吃的面,他就给你做
    //拉面师傅
    public Cook{
     
        public static Noodle createNoodle(int type){
     
            switch(type){
     
                case 0:
                    return new HandPulledNoodle();
                case 1:
                    return new InstantNoodle();
                case 2:
                    return new DryBuckleSurface();
                default:
                    return new DryBuckleSurface();
            }
        }
    
    }

小明想吃家乡的干扣面便告诉师傅.

    public class Ming{
     
        public static void main(String[] args){
     
            Noodle noodle = Cook.createNoodle(2);
            noodle.desc();
        }
    }

工厂方法模式

上述模式不适用解耦,若再增加需求就需要改动原有代码,并不建议,所以如下提供工厂方法模式。
从前有个皇帝。他叫小明,特爱干净每天都要换衣服,所以让每个宫女负责一种衣服。需要的时候叫宫女去做。
    //衣服接口
    public interface Dress{
     
        //衣服描述
        void desc();
    }
    
    //衣服具体实现
    public class RedDress{
     
        public void desc(){
     
            System.out.println("红衬衫");
        }
    }
    
    public class GreenDress{
     
        public void desc(){
     
            System.out.println("绿衬衫");
        }
    }
    
    //宫女接口
    public interface MaidInWaiting{
     
        Dress createDress();
    }
    
    //宫女的具体实现,负责红色衣服
    public class RedLadyInWaiting implements MaidInWaiting{
     
        public static Dress createDress(){
     
            return new RedDress();
        }
    }
    
    //宫女的具体实现,负责绿色衣服
    public class GreenLadyInWaiting implements MaidInWaiting{
     
        public static Dress createDress(){
     
            return new GreenDress();
        }
    }

小明想穿红色衣服

    public class Main{
     
        public static void main(String[] args){
     
            MaidInWaiting wait = new RedLadyInWaiting();
            Dress dress = wait.createDress();
            dress.desc();
        }
    }

抽象工厂模式

所谓抽象工厂模式即,包含以下类:
    多个抽象工厂类
    多个抽象工厂实现类
    多个抽象产品类
    多个抽象产品实现类
    //怪物抽象工厂
    public interface MasterFactory{
     
        Master createMaster();
    }
    
    //管道抽象工厂
    public interface PipelineFactory{
     
        Pipeline createPipeline();
    }
    
    //乌龟怪物工厂实现类
    public class TortoiseFactory implements MasterFactory{
     
        public Master createMaster(){
     
            return new Tortoise();
        }
    }
    
    //魔鬼怪物工厂实现类
    public class DevilFactory implements MasterFactory{
     
        public Master createMaster(){
     
            return new Devil();
        }
    }
    
    //管道工厂实现类
    public class IPipelineFactory implement PipelineFactory{
     
        public Pipeline createPipeline(){
     
            return new IPipeline();
        }
    }
    //怪物抽象类
    public interface Master{
     
        void move();
    }
    //管道抽象类
    public interface Pipeline{
     
        void desc();
    }
    
    //管道实现类
    public class IPipeline implement Pipeline{
     
        public void desc(){
     
            System.out.println("绿色管道");
        }
    }
    
    //怪物实现类    乌龟
    public class Tortoise implements Master{
     
        public void move(){
     
            System.out.println("缓慢移动");
        }
    }
    
    //怪物实现类  魔鬼
    public class Devil implements Master{
     
        public void move(){
     
            System.out.println("飞行移动");
        }
    }
    
    public class Main{
     
        public static void main(String[] args){
     
            MasterFactory tf = new TortoiseFactory();
            Master tortoise = tf.createMaster();
            tortoise.move();
        }
    }
    

策略模式

一、策略模式定义
    定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们之间可以相互替换,策略 模式可以在不影响客户端的情况下发生变化。
二、策略模式涉及到的三个角色
    环境(Context)角色  持有一个Strategy的引用
    抽象策略(Strategy)角色 这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
    具体策略(ConcreteStrategy)角色  包装了具体的算法或行为。

举个例子吧
        //腾讯客服招待方式抽象接口
        public interface Treat{
     
            void say();
        }
        
        //机器人客服
        public class RobotTreat implements Treat{
     
            public void say(){
     
                System.out.println("你好,我是小强机器人,很高兴为你服务");
            }
        }
        
        public class Person implements Treat{
     
            public void say(){
     
                System.out.println("尊贵的心悦会员您好,我是您的专用客服,很高兴为您服务!");
            }
        }
        
        public class Context{
     
            private Treat treat;
            
            public Context(Treat treat){
     
                this.treat = treat;
            }
            
            public void setTreat(Treat treat){
     
                this.treat = treat;
            }
            
            public void say(){
     
                treat.say();
            }
        }
        
        public class Main{
     
            public static void main(String[] args){
     
                //对待不同的用户调用不同的策略来进行处理
                //普通用户
                Context context = new Context(new RobotTreat());
                context.say();
                //心悦会员
                context.setTreat(new Person());
                context.say();
            }
        }

装饰者模式

  动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。

设计原则:

  • 多用组合,少用继承。
  • 类应设计的对扩展开放,对修改关闭。
    
    //狼接口 被装饰接口
    interface Wolf{
     				
    	public abstract void display();
    }
    
    //被装饰类	灰太狼
    class Wolffy implements Wolf{
     		
    	@Override
    	public void display() {
     
    		System.out.println("灰太狼正在准备食材");
    	}
    }
    
    //装饰者类A	红太狼	内部维护一只狼
    class Hollie implements Wolf{
     	
    	private Wolf wolf;
    	
    	public Hollie(Wolf wolf) {
      this.wolf = wolf; }
    	@Override
    	public void display() {
     
    		System.out.println("红太狼正在烧水准备煮羊");
    		wolf.display();
    	}
    }
    
    //装饰者类B	小灰灰狼	内部维护一只狼
    class Howie implements Wolf{
     	
    	private Wolf wolf;	
    	
    	public Howie(Wolf wolf){
      this.wolf = wolf; }
    	
    	@Override
    	public void display() {
     
    		wolf.display();
    		System.out.println("小灰灰放走了小羊们");
    	}
    } 
    
    //测试类
    public class DeckerDemo {
     
    	public static void main(String[] args) {
     
    		Wolf wolffy = new Wolffy();
    		Wolf hollie = new Hollie(wolffy);
    		Wolf howie = new Howie(hollie);
    		howie.display();
    	}
    }

观察者模式

    定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。
  • 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
  • 当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
  • 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。
    public class LookerDemo {
     
	public static void main(String[] args) {
     
		Potence ming = new Team("小明");
		Potence zang = new Team("小张");
		Potence liang = new Team("小亮");
		Potence hua = new Team("小花");
		Tyfon.addTeam(ming);
		Tyfon.addTeam(zang);
		Tyfon.addTeam(liang);
		Tyfon.addTeam(hua);
		ming.removePerson(hua);
		ming.removePerson(liang);
		ming.removePerson(zang);
	}
}


    //大喇叭消息发送中心
    class Tyfon{
     
    	private static List<Potence> potences = new ArrayList<>();
    	
    	//添加参赛人员
    	public static void addTeam(Potence potence){
     
    		potences.add(potence);
    	}
    	
    	//向参赛人员发送消息
    	public static void sendMessage(String msg){
     
    		for (Potence p : potences) {
     
    			p.update(msg);
    		}
    		System.out.println("剩余参赛人员:"+potences);
    	}
    	
    	//删除参加人员
    	public static void remove(Potence potence){
     
    		potences.remove(potence);
    	}
    	
    }
    
    
    //消息接收器
    abstract class Potence{
     
    	//参赛人员
    	protected String name;
    	public String getName() {
     
    		return name;
    	}
    	public Potence(String name){
     
    		this.name = name;
    	}
    	
    	//接受消息
    	abstract void update(String msg);
    	
    	//干掉其他参赛人员
    	abstract void removePerson(Potence potence);
    }
    
    
    class Team extends Potence{
     
    	public Team(String name){
     
    		super(name);
    	}
    	
    	@Override
    	public void update(String msg) {
     
    		System.out.println(name+"收到消息: "+msg);
    	}
    	
    	@Override
    	public void removePerson(Potence potence) {
     
    		Tyfon.remove(potence);
    		Tyfon.sendMessage(name+"干掉了"+potence.getName());
    	}
    	
    	@Override
    	public String toString() {
     
    		return getName();
    	}
    }

适配器模式

    适配器模式(Adapter):将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

众所周知,小米6没有耳机接口,只有个Type-C的充电口,而通常的耳机都是圆孔的插头(OMTP),这是就需要转换。
    public class AdapterDemo {
     
    	public static void main(String[] args) {
     
    	    //大概相当于买了个耳机
    		OMTP omtp = new IOMTP();
    		//大概相当于买了个Type-C转换器,并把耳机插在转换器上。
    		TypeC converter = new Converter(omtp);
    		//大概相当于把Type-C转换器插在手机上,然后听歌
    		converter.useTypeC();
    	}
    }
    
    //Type-C接口		大部分手机已去除OMTP耳机接口,仅留下Type-C接口
    interface TypeC{
     
    	void useTypeC();
    }
    
    //OMTP插头	大部分耳机都是OMTP插头
    interface OMTP{
     
    	void useOMTP();
    }
    
    //OMTP插头 耳机上转用
    class IOMTP implements OMTP{
     
    	@Override
    	public void useOMTP() {
     
    		System.out.println("使用OMTP听歌");
    	}
    }
    
    //插口转换器		把耳机的插头插在转换器上,再把转换器的Type-C插在手机上的Type-C接口上就可使用
    class Converter implements TypeC{
     
    	private OMTP omtp;
    	public Converter(OMTP omtp){
     
    		this.omtp=omtp;
    	}
    	
    	@Override
    	public void useTypeC() {
     
    		omtp.useOMTP();
    	}
    }
    该方式是通过组合的方式来完成适配的,同时也可以继承方式来完成。为了降低程序的耦合度,建议使用组合方式,所以继承方式就不详细叙述了,请自行查阅。

代理模式

    代理是一种模式,提供了对目标对象的间接访问方式,即通过代理访问目标对象。如此便于在目标实现的基础上增加额外的功能操作,前拦截,后拦截等,以满足自身的业务需求,同时代理模式便于扩展目标对象功能的特点也为多人所用。

静态代理

    静态代理的实现比较简单,代理类通过实现与目标对象相同的接口,并在类中维护一个代理对象。通过构造器塞入目标对象,赋值给代理对象,进而执行代理对象实现的接口方法,并实现前拦截,后拦截等所需的业务功能。
    public class ProxyDemo {
     
    	public static void main(String[] args) {
     
    		//突然兴致勃勃想上分打游戏
    		Me me = new Me();
    		me.playGame();
    		//太菜了,一直掉分,还是找个代练吧
    		Play play = new Proxyer(me);
    		play.playGame();
    	}
    }
    
    interface Play{
     
    	void playGame();
    }
    
    //我
    class Me implements Play{
     
    	@Override
    	public void playGame() {
     
    		System.out.println("玩游戏");
    	}
    }
    
    //代练
    class Proxyer implements Play{
     
    	private Me me;
    	public Proxyer(Me me) {
     
    		this.me = me;
    	}
    	
    	//代替我玩游戏
    	@Override
    	public void playGame() {
     
    		me.playGame();
    	}
    }

JDK动态代理

    public class ProxyDemo {
     
    	public static void main(String[] args) {
     
    		//突然兴致勃勃想上分打游戏
    		Me me = new Me();
    		me.playGame();
    		//太菜了,一直掉分,还是找个代练吧
    		Play p = (Play) Proxyer.factory(me);
    		p.playGame();
    	}
    }
    
    /**
     * 我们玩LOL抢位置,有时候抢不到,而代练们也是擅长不同位置,所以我们找的代练一般都是一个工作室,不止一个代练。会根据玩LOL的位置来动态换的。
     */
    interface Play{
     
    	void playGame();
    }
    
    //我
    class Me implements Play{
     
    	@Override
    	public void playGame() {
     
    		System.out.println("玩游戏");
    	}
    }
    
    
    //代练
    class Proxyer implements InvocationHandler{
     
    	private Object terget;
    	public Proxyer(Object terget) {
     
    		this.terget = terget;
    	}
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     
    		return method.invoke(terget,args);
    	}
    	
    	public static Object factory(Object obj){
     
    		Class clazz = obj.getClass();
    		return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),new Proxyer(obj));
    	}
    }

CGLIB动态代理

    使用Cglib实现动态代理,并不要求委托类必须实现接口,底层采用asm字节码生成框架生成代理类的字节码。

代理模式的应用形式

  • 远程代理(Remote Proxy) - 可以隐藏一个对象存在于不同地址空间的事实。也使得客户端可以访问在远程机器上的对象,远程机器可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。
  • 虚拟代理(Virtual Proxy) – 允许内存开销较大的对象在需要的时候创建。只有我们真正需要这个对象的时候才创建。
  • 写入时复制代理(Copy-On-Write Proxy) – 用来控制对象的复制,方法是延迟对象的复制,直到客户真的需要为止。是虚拟代理的一个变体。
  • 保护代理(Protection (Access)Proxy) – 为不同的客户提供不同级别的目标对象访问权限
  • 缓存代理(Cache Proxy) – 为开销大的运算结果提供暂时存储,它允许多个客户共享结果,以减少计算或网络延迟。
  • 防火墙代理(Firewall Proxy) – 控制网络资源的访问,保护主题免于恶意客户的侵害。
  • 同步代理(SynchronizationProxy) – 在多线程的情况下为主题提供安全的访问。
  • 智能引用代理(Smart ReferenceProxy) - 当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。
  • 复杂隐藏代理(Complexity HidingProxy) – 用来隐藏一个类的复杂集合的复杂度,并进行访问控制。有时候也称为外观代理(Façade Proxy),这不难理解。复杂隐藏代理和外观模式是不一样的,因为代理控制访问,而外观模式是不一样的,因为代理控制访问,而外观模式只提供另一组接口。

原型模式

    克隆的对象可能包含一些已经修改过的属性,保留着你想克隆对象的值,而new出来的对象的属性全是一个新的对象,对应的属性没有值,所以我们还要重新给这个对象赋值。即当需要一个新的对象来保存当前对象的“状态”就靠clone方法了。

实现克隆的方式

  • 对象的类实现Cloneable接口;
  • 覆盖Object类的clone()方法 (覆盖clone()方法,访问修饰符设为public,默认是protected);
  • 在clone()方法中调用super.clone();
    ####克隆的两种方法
  • 浅克隆是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象,但会把克隆出来的对象中对对象的引用指向被克隆对象中对象引用的对象。
  • 深克隆不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。

浅克隆

    public class CloneDemo {
     
	public static void main(String[] args) throws CloneNotSupportedException {
     
		//灰太狼抓到喜羊羊,觉得不够吃,就想办法克隆多个出来
		Sheep sheep = new Sheep("喜羊羊");
		Sheep sheep1 = (Sheep) sheep.clone();
		sheep.desc();
		sheep1.desc();
	}
}

class Sheep implements Cloneable{
     
	private String name;
	private String age;
	
	public Sheep(String name){
     
		this.name = name;
	}
	public void desc(){
     
		System.out.println("我是"+name);
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
     
		return super.clone();
	}
}

深克隆

    public class CloneDemo {
     
	public static void main(String[] args) throws CloneNotSupportedException {
     
		//浅克隆人技术
		IPerson person = new IPerson("爱丽丝",new Memory("我出生于美国,我有个完美的家庭"));
		person.desc();
		IPerson person2 = (IPerson) person.clone();
		//person.getMemory().setContent("我很好");
		person2.desc();
		//浅克隆人技术 在克隆记忆的时候就出现了问题,
		//完美状态应该是克隆一份,而现在确实把克隆出来的人的记忆指向了原来的人,当原来人的记忆发生变化时,克隆人也会跟着变化
		//这是个缺陷
		//要解决这个问题就需要在clone方法中进行系列操作完成深克隆
		IPerson person22 = new IPerson("爱丽丝",new Memory("我出生于美国,我有个完美的家庭"));
		person.desc();
		IPerson person222 = (IPerson) person22.clone();
		person.getMemory().setContent("我很好");
		person2.desc();
		
		//深克隆技术
		//若克隆的实例中包含对象,则在包含对象中同样实现Cloneable,在克隆的实例类中的clone方法中同时克隆引用的对象.
		
	}
}

class IPerson implements Cloneable{
     
	private String name;
	private Memory memory;
	
	public IPerson(String name,Memory memory){
     
		this.name = name;
		this.memory = memory;
	}
	
	public void desc(){
     
		System.out.println("我是"+name);
		if (memory!=null) {
     
			memory.desc();
		}else{
     
			System.out.println("我记忆丢失了");
		}
	}
	
	public Memory getMemory() {
     
		return memory;
	}
	
	public void setMemory(Memory memory) {
     
		this.memory = memory;
	}
	
//	//浅克隆
//	@Override
//	protected Object clone() throws CloneNotSupportedException {
     
//		// TODO Auto-generated method stub
//		return super.clone();
//	}
	
	//深克隆
	@Override
	protected Object clone() throws CloneNotSupportedException {
     
		IPerson person = (IPerson) super.clone();
		if (person.getMemory()!=null) {
     
			Memory memory = (Memory) person.getMemory().clone();
			person.setMemory(memory);
		}
		return person;
	}
}

//记忆
class Memory implements Cloneable{
     
	private String content;
	public Memory(String content){
     
		this.content = content;
	}
	public void setContent(String content) {
     
		this.content = content;
	}
	
	public void desc(){
     
		System.out.println(content);
	}
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
     
		// TODO Auto-generated method stub
		return super.clone();
	}
}

模板方法模式

定义

    定义一个操作中算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤。
    不变的部分留在abstract类中,继承该类实现abstract方法。

作用

  • 提高代码复用性
    将相同部分的代码放在抽象的父类中,而将不同的代码放入不同的子类中
  • 实现了反向控制
    通过一个父类调用其子类的操作,通过对子类的具体实现扩展不同的行为,实现了反向控制 & 符合“开闭原则”
    abstract class Drink{
     
	//煮
	public void boil(){
     
		heatUpWater();
		addMainMaterial();
		filter();
		addChargeMixture();
	}
	
	public void heatUpWater(){
     
		System.out.println("烧水");
	}
	
	public abstract void addMainMaterial();
	
	public void filter(){
     
		System.out.println("过滤");
	}
	
	public abstract void addChargeMixture();
}

//茶
//烧茶步骤		烧水->茶叶->过滤->加柠檬
class teaOilTree extends Drink{
     
	@Override
	public void addMainMaterial() {
     
		System.out.println("加茶叶");
	}

	@Override
	public void addChargeMixture() {
     
		System.out.println("加柠檬");
	}
}

//咖啡		烧水->咖啡粉->过滤->加糖加奶
class Coffee extends Drink{
     

	@Override
	public void addMainMaterial() {
     
		System.out.println("加咖啡粉");
	}

	@Override
	public void addChargeMixture() {
     
		System.out.println("加糖加奶");
	}
	
}

public class TemplateMethodDemo {
     
	public static void main(String[] args) {
     
		//烧茶
		Drink drink = new teaOilTree();
		drink.boil();
		
		//烧咖啡
		Drink coffee = new Coffee();
		coffee.boil();
		
	}
}

外观模式

    提供一个单独的对外接口,用于作为外部应用和内部复杂系统的桥梁。外部 应用不必知道系统内部的实现细节。

例子
> * 平常灰太狼捉羊羊是很麻烦的事情 打探情报 设置陷阱 诱惑羊羊 捕捉

public class AppearanceDemo {
     
	public static void main(String[] args) {
     
		IWolffy wolffy = new IWolffy();
		wolffy.monitor();
		wolffy.pitfall();
		wolffy.entice();
		wolffy.seize();
	}
}

//灰太狼类
class IWolffy{
     
	public void monitor(){
     
		System.out.println("打探情报");
	}
	public void pitfall(){
     
		System.out.println("设置陷阱");
	}
	public void entice(){
     
		System.out.println("诱惑羊羊");
	}
	public void seize(){
     
		System.out.println("捕捉");
	}
}
  • 后来灰太狼想偷偷懒,不想亲自抓了,就做了个机器灰太狼。
    public class AppearanceDemo {
     
	public static void main(String[] args) {
     
		IWolffy wolffy = new IWolffy(new WolffyRobot());
		wolffy.catchSheep();
	}
}

//灰太狼
class IWolffy{
     
	private WolffyRobot wolffyRobot;
	public IWolffy(WolffyRobot wolffyRobot){
     
		this.wolffyRobot = wolffyRobot;
	}
	//捉羊
	public void catchSheep(){
     
		wolffyRobot.monitor();
		wolffyRobot.pitfall();
		wolffyRobot.entice();
		wolffyRobot.seize();
	}
}

//机器灰太狼 打探情报 设置陷阱 诱惑羊羊 捕捉
class WolffyRobot{
     
	public void monitor(){
     
		System.out.println("打探情报");
	}
	
	public void pitfall(){
     
		System.out.println("设置陷阱");
	}
	
	public void entice(){
     
		System.out.println("诱惑羊羊");
	}
	public void seize(){
     
		System.out.println("捕捉");
	}
}

建造者模式

    将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
    工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象,所谓复合对象就是指某个类具有不同的属性。

应用实例:
日常玩游戏中刷装备,鞋子,裤子,铠甲等是不变的,而套装确是经常变的。

    public class BuilderDemo {
     
    	public static void main(String[] args) {
     
    		BuildSuit buildSuit = new MainBuilder();
    		Suit createSuit = Executant.createSuit(buildSuit);
    		
    		System.out.println(createSuit);
    		//获取新套装
    		buildSuit = new IMainBuilder();
    		Suit suit = Executant.createSuit(buildSuit);
    		System.out.println(suit);
    		
    	}
    }
    
    /**
     * 
     * 装备和套装	
     */
    //装备
    interface Equip{
     
    	void desc();
    }
    
    //史诗头盔
    class Casque implements Equip{
     
    	@Override
    	public void desc() {
     
    		System.out.println("史诗·索尼娅的头盔");
    	}
    }
    
    //史诗铠甲
    class  Armour implements Equip{
     
    	@Override
    	public void desc() {
     
    		System.out.println("史诗·索尼娅的铠甲");
    	}
    }
    
    //史诗裤子
    class Trousers implements Equip{
     
    	@Override
    	public void desc() {
     
    		System.out.println("史诗·索尼娅的裤子");
    	}
    }
    
    //传奇头盔
    class ICasque implements Equip{
     
    	@Override
    	public void desc() {
     
    		System.out.println("传奇·比索亚的头盔");
    	}
    }
    
    //传奇铠甲
    class  IArmour implements Equip{
     
    
    	@Override
    	public void desc() {
     
    		System.out.println("传奇·比索亚的铠甲");
    	}
    }
    
    //传奇裤子
    class ITrousers implements Equip{
     
    	@Override
    	public void desc() {
     
    		System.out.println("传奇·比索亚的裤子");
    	}
    }
    
    /****************↑↑↑↑↑↑↑↑↑↑  套装中的具体装备  ↑↑↑↑↑↑↑↑↑↑↑↑↑↑********************/
    
    
    //套装		要创建的套装
    class Suit{
     
    	private Equip casque;
    	private Equip armour;
    	private Equip trousers;
    		
    	public Equip getArmour() {
     
    		return armour;
    	}
    	public void setArmour(Equip armour) {
     
    		this.armour = armour;
    	}
    	
    	public Equip getCasque() {
     
    		return casque;
    	}
    	public void setCasque(Equip casque) {
     
    		this.casque = casque;
    	}
    	public Equip getTrousers() {
     
    		return trousers;
    	}
    	public void setTrousers(Equip trousers) {
     
    		this.trousers = trousers;
    	}
    	@Override
    	public String toString() {
     
    		casque.desc();
    		armour.desc();
    		trousers.desc();
    		return "";
    	}
    }
    
    //套装建造者接口	规范套装的各个组成成分的建造。这个接口规定要实现套装中哪些部位的创建,并不涉及 具体装备的创建
    interface BuildSuit{
     
    	void buildCasque();
    	void buildArmour();
    	void buildTrousers();
    	Suit createSuit();
    }
    
    //史诗套装建造者
    class MainBuilder implements BuildSuit{
     
    	private Suit suit;
    	
    	public MainBuilder() {
     
    		suit = new Suit();
    	}
    	@Override
    	public void buildCasque() {
     
    		suit.setCasque(new Casque());
    	}
    
    	@Override
    	public void buildArmour() {
     
    		suit.setArmour(new Armour());
    	}
    
    	@Override
    	public void buildTrousers() {
     
    		suit.setTrousers(new Trousers());
    	}
    	@Override
    	public Suit createSuit(){
     
    		return suit;
    	}
    }
    
    //传奇套装建造者	实现BuilderSuit接口,针对不同的套装,具体化套装中的各个装备。 在建造过程完成后,提供整个套装
    class IMainBuilder implements BuildSuit{
     
    	private Suit suit;
    	
    	public IMainBuilder() {
     
    		suit = new Suit();
    	}
    	
    	@Override
    	public void buildCasque() {
     
    		suit.setCasque(new ICasque());
    	}
    
    	@Override
    	public void buildArmour() {
     
    		suit.setArmour(new IArmour());
    	}
    
    	@Override
    	public void buildTrousers() {
     
    		suit.setTrousers(new ITrousers());
    	}
    	@Override
    	public Suit createSuit(){
     
    		return suit;
    	}
    }
    
    //执行者		调用具体建造者来创建套装的各个部分,在执行者中不涉及具体套装的信息,只负责保证对象各部分完整创建或按某种顺序创建
    class Executant{
     
    	public static Suit createSuit(BuildSuit builder){
     
    		builder.buildArmour();
    		builder.buildCasque();
    		builder.buildTrousers();
    		return builder.createSuit();
    	}
    }

组合模式

    将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
  • People 组合中的对象生命接口,在适当情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理People的子部件。
  • Man 定义有枝节点的行为,用来存储子部件,在People接口中实现与子部件有关的操作。
  • Wuman 在组合中表示叶节点对象,叶节点没有子节点。
    
    interface People {
     
    	void desc();
    	void remove(People people);
    	void add(People people);
    	void each();
    }
    
    //  男人类  枝节点      内部存储子节点  实现与子部件有关的操作。
    class Man implements People{
     
        //子节点集合
    	private List<People> childs = new ArrayList<>();
    	
    	@Override
    	public void desc() {
     
    		System.out.println("男人");
    	}
    
    	@Override
    	public void remove(People people) {
     
    		childs.remove(people);
    	}
    
    	@Override
    	public void add(People people) {
     
    		childs.add(people);
    	}
    	public List<People> getChilds() {
     
    		return childs;
    	}
    
    	@Override
    	public void each() {
     
    		for (People people : childs) {
     
    			people.desc();
    		}
    	}
    }
    
    //女人     叶节点   内部没有子节点      家族传承断了
    public class Wuman implements People{
     
    	@Override
    	public void desc() {
     
    		System.out.println("女人");
    	}
    
    	@Override
    	public void remove(People people) {
     
    	}
    
    	@Override
    	public void add(People people) {
     
    		
    	}
    
    	@Override
    	public void each() {
     
    	}
    }
    
    /**
     * 计算人类繁衍		男人则繁衍后代,女人则结束。
     * @author Keben
     *
     */
    public class Test {
     
    	static Random random = new Random();
    	static Long count = 0l;
    	public static void main(String[] args) {
     
    		People people = new Man();
    		//计算1000个人繁衍到灭绝的人数
    		for(int i = 0;i<1000;i++){
     
    			multiply(createPeople());
    		}
    	}
    	public static void multiply(People people){
     
    		if (people instanceof Man) {
     
    			//每个男人生养0-4个孩子
    			int i = random.nextInt(5);
    			for (int j = 0; j < i; j++) {
     
    				people.add(createPeople());
    			}
    			Man man = (Man)people;
    			for(People p : man.getChilds()){
     
    				//每个孩子又分别繁衍后代
    				multiply(p);
    				count++;
    			}
    		}else{
     
    			count++;
    		}
    		System.out.println(count);
    	}
    	
    	//随机创建男孩女孩。
    	public static People createPeople(){
     
    		int i = random.nextInt(2);
    		if (i==0) {
     
    			return new Wuman();
    		}else{
     
    			return new Man();
    		}
    	}
    }
    组合模式又分为透明组合模式和安全组合模式。
  • 透明组合模式,即同上述代码。People接口定义关于对子节点操作,在枝节点和叶节点中实现,其中枝节点中的实现是具体实现,而叶节点则是空实现,虽然实现了People接口,但方法里并没有任何操作。透明组合模式的缺点是不够安全,因为叶子对象和容器对象在本质上是有区别的。叶子对象不可能有下一层的对象,即不可能包含成员对象。因此为其提供对子节点操作的方法是没有意义的,编译没问题,运行阶段调用这些操作可能会有问题。
     
  • 安全组合模式,在People接口中不定义关于对子节点的操作,而是在枝节点中定义关于对子节点的操作即在Man中定义,这种方式是安全的,因为根本不向叶子Wuman对象提供对子节点操作的方法,安全组合模式缺点是不够透明,因为叶子组件和枝节点具有不同的方法,且枝节点中那些对子节点操作的方法并没有在People接口中定义,因此客户端不能完全针对抽象变成。在实际开发中,安全组合模式使用频率非常高,Java中的AWT的使用的组合模式就是安全组合模式。

迭代器模式

    提供一种方法顺序访问一个聚合对象中各个元素,而又不暴漏对象的内部表示。
  • 迭代器角色(Itertor):迭代器角色负责定义访问和遍历元素的接口。
  • 具体迭代器角色(PersonItertor):具体迭代器角色要实现迭代器接口,并要记录遍历中的当前位置。
  • 容器角色(Person):容器角色负责提供创建具体迭代器角色的接口。
  • 具体容器角色(Crowd):具体容器角色实现创建具体迭代器角色的接口——这个具体迭代器角色于该容器的结构相关。
    public class Test {
     
    	public static void main(String[] args) {
     
    		Crowd crowd = new Crowd();
    		for(int i = 0; i<10;i++){
     
    			crowd.addPerson(new Person("老王"+i));
    		}
    		Itertor it = crowd.createItertor();
    		while (it.isHasNext()) {
     
    			Person next = (Person) it.next();
    			next.desc();
    		}
    	}
    }

    interface Itertor{
     
    	//获取下一个元素
    	Object next();
    	//是否有下一个元素
    	boolean isHasNext();
    }
    
    //人
    class Person{
     
    	private String name;
    	public Person(String name){
     
    		this.name = name;
    	}
    	public void desc(){
     
    		System.out.println(name);
    	}
    }
    
    //人群
    class Crowd{
     
    	private List<Person> persons = new ArrayList<>();
    	
    	public void addPerson(Person person){
     
    		this.persons.add(person);
    	}
    	
    	public void removePerson(Person person){
     
    		this.persons.remove(person);
    	}
    	
    	public Itertor createItertor(){
     
    		return new PersonItertor();
    	}
    	
    	class PersonItertor implements Itertor{
     
    		int index = 0;
    		
    		@Override
    		public Object next() {
     
    			if (index<persons.size()) {
     
    				return persons.get(index++);
    			}
    			return null;
    		}
    		@Override
    		public boolean isHasNext() {
     
    			return index<persons.size();
    		}
    	}
    }

桥接模式

    桥接模式是用于“把抽象和实现分开,这样它们就能独立变化”。
    桥接模式使用了封装、聚合,可以用继承将不同的功能拆分为不同的类。
  • 电视和遥控器是一个完美展示两层抽象的例子。你有一个电视机的接口,还有一个遥控器的抽象类。我们都知道,将它们中任何一个定义为一个具体类都不是好办法,因为其它厂家会有不同的实现方法。
    public class Test {
     
    	public static void main(String[] args) {
     
    		TV tv = new MiTV();
    		TeleController tc = new MiTeleController(tv);
    		tc.change(10);
    	}
    }
    
    //电视机接口
    abstract class TV{
     
    	abstract void on();
    	abstract void off();
    	public void change(int index){
     
    		System.out.println("换台"+index);
    	}
    }
    
    class MiTV extends TV{
     
    	@Override
    	public void on() {
     
    		System.out.println("小米电视,畅想奇迹未来,开机");
    	}
    
    	@Override
    	public void off() {
     
    		System.out.println("小米电视,再见");
    	}
    }
    
    class HTCTV extends TV{
     
    	@Override
    	public void on() {
     
    		System.out.println("HTC,开机");
    	}
    
    	@Override
    	public void off() {
     
    		System.out.println("HTC,再见");
    	}
    }
    
     //遥控器接口	内部维护一个TV接口
    abstract class TeleController{
     
    	private TV tv;
    	public TeleController(TV tv){
     
    		this.tv = tv;
    	}
    
    	public void turnOn(){
     
    		tv.on();
    	}
    	
    	public void turnOff(){
     
    		tv.off();
    	}
    	
    	public void	change(int index){
     
    		tv.change(index);
    	}
    }
     
    //小米遥控器
    class MiTeleController extends TeleController{
     
    	public MiTeleController(TV tv) {
     
    		super(tv);
    	}
    	
    	@Override
    	public void change(int index) {
     
    		super.change(index);
    		System.out.println("Mi遥控器");
    	}
    }

享元模式

    享元模式通过尽可能的复用已经存在的对象,从而尽量少的创建新对象,以节约系统的内存和提供系统性能。在享元模式中,对象的属性分为两种,内部状态和外部状态。内部状态指的是对象中不随外部变化的属性,属于对象本身的特征属性(比如ID)。外部状态指的是对象中可以随外部变化的属性,可以在外部设置对象的外部状态。

    享元模式的思想就是缓存和复用,重点关注的是性能。所以当系统中存在大量的对象,内存开销较大或者对象的大部分的属性是外部状态情况下,可以考虑享元模式。抽象一下,可以通过缓存解决的问题,一般都可以应用享元模式。
  • Show 享元接口或者(抽象享元类),定义共享接口
  • Model 具体享元类,该类实例将实现共享
  • ModelFactory 享元工厂类,控制实例的创建和共享
    维多利亚的秘密是最高等级的秀场,全世界的超模也以能登上维秘秀舞台为傲。对于每一套造型(对象)来说,包含模特(对象的内部状态)和服装(对象的外部状态)。能使用的模特是有限的,但是要展示的服装却要远远超出这个数量,所以在展示每一套服装的时候,需要对模特进行复用。导演要展示一个造型,只需要从目前可用的模特人群(缓存)中喊一个过来,穿上对应的服装,即可走上T台。那么如果目前没有可用的模特怎么办呢?那就招个模特进来,实在不行导演自己上咯。
    public class Demo {
     
    	public static void main(String[] args) {
     
    		Show model = ModelFactory.getShow("米兰达·可儿");
            model.setStyle("迷幻Bono系列");
            model.show();
     
            model = ModelFactory.getShow("刘雯");
            model.setStyle("冰与火系列");
            model.show();
            model = ModelFactory.getShow("米兰达·可儿");
            model.setStyle("天使肖像系列");
            model.show();
    
    	}
    }
    
    //走秀
    interface Show{
     
    	void show();
    	void setStyle(String style);
    }
    
    //模特
    class Model implements Show{
     
    	private String name;
    	private String style;
    	
    	public Model(String name) {
     
    		this.name = name;
    	}
    	
    	@Override
    	public void show() {
     
    		System.out.println(name+"-"+style);
    	}
    	
    	@Override
    	public void setStyle(String style) {
     
    		this.style = style;
    	}
    }
    
    //工厂
    class ModelFactory{
     
    	private static Map<String,Show> threadMap = new HashMap<>();	//对象池
    	
    	public static Show getShow(String name){
     
    		if (threadMap.get(name)!=null){
     
    			return threadMap.get(name);
    		}else{
     
    			Show show = new Model(name);
    			threadMap.put(name, show);
    			return show;
    		}
    	}
    }

备忘录模式

    备忘录模式,即保存某个对象内部状态的拷贝,这样以后就可以将该对象恢复到原先的状态。
  • 发起者角色(GameRole):负责创建一个备份用以记录当前时刻它的内部状态,并可以使用备份恢复内部状态。
  • 备忘录角色(Backup):负责存储GameRole的内部状态,并可以防止GameRole以外的其他对象访问备忘录。
  • 管理者角色(Ruler):负责保存好备忘录并不访问备份的内部。
    public class Demo {
     
    	public static void main(String[] args) {
     
    		GameRole gameRole = new GameRole();
    		gameRole.setLv(10);
    		gameRole.setBv(100);
    		gameRole.desc();
    		Ruler ruler = new Ruler(gameRole.createBackup());
    		gameRole.setBv(0);
    		gameRole.desc();
    		System.out.println("You dead!");
    		System.out.println("加载备份数据....");
    		gameRole.recoverBackup(ruler.getBackup());
    		gameRole.desc();
    	}
    }
    
    /**
     *  GameRole	游戏打Boss前备份下。
     * 	游戏角色	玩家的参数	同时提供备份和恢复的功能
     *  Backup		备份数据对象
     *  Ruler       管理者	负责管理备份
     */
    class GameRole{
     
    	private int lv;	//等级
    	private int bv;	//血量
    	
    	public int getLv() {
     
    		return lv;
    	}
    	
    	public void setLv(int lv) {
     
    		this.lv = lv;
    	}
    	
    	public int getBv() {
     
    		return bv;
    	}
    	
    	public void setBv(int bv) {
     
    		this.bv = bv;
    	}
    	
    	public Backup createBackup(){
     
    		return new Backup(this);
    	}
    	
    	public void recoverBackup(Backup backup){
     
    		this.lv = backup.getLv();
    		this.bv = backup.getBv();
    	}
    	
    	public void desc(){
     
    		System.out.println("等级:"+lv+",血量:"+bv);
    	}
    }
    
    class Backup{
     
    	private int lv;
    	private int bv;
    	
    	public Backup(GameRole gameRole) {
     
    		this.lv = gameRole.getLv();
    		this.bv = gameRole.getBv();
    	}
    	
    	public int getLv() {
     
    		return lv;
    	}
    	
    	public int getBv() {
     
    		return bv;
    	}
    }
    
    class Ruler{
     
    	private Backup backup;
    	
    	public Ruler(Backup backup){
     
    		this.backup = backup;
    	}
    	
    	public Backup getBackup() {
     
    		return backup;
    	}
    	
    	public void setBackup(Backup backup) {
     
    		this.backup = backup;
    	}
    }

相比与简单的原型模式为什么用较复杂的备忘录模式呢?

    备忘录模式用于保存和恢复对象的状态,相信大家看过我前面的拙作就会想到原型模式也能保存一个对象在某一个时刻的状态,那么两者有何不同的呢?原型模式保存的是当前对象的所有状态信息,恢复的时候会生成与保存的对象完全相同的另外一个实例;而备忘录模式保存的是我们关心的在恢复时需要的对象的部分状态信息,相当于快照。
  • 当备忘点较多时
    设置栈将备忘点压栈
    将多个备忘录对象持久化和序列化保存到本地
  • 优点
    备忘录模式可以把发起人内部信息对象屏蔽起来,从而可以保持封装的边界。
    简化了发起人类。当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
  • 缺点
    如果状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象比较昂贵。
当发起者对象的状态改变的时候,有可能这个协议无效。如果状态改变的成功率达不到要求,可以考虑采取“假如”协议模式。

责任链模式

    责任链模式是一种线性执行流程,多个对象都有机会去执行同一个任务,只是在执行过程中,由于执行的权利和范围不一样,那么当自己不能处理此任务时,就必须将这个任务抛给下一个对象,一次类推,就形成了一个执行链。例如,小明请假,自己没有权限处理,向上级处理,若请假时间太长,则上级向上级的上级处理,以此类推,没权限处理则向上抛。
    public class Demo {
     
    	public static void main(String[] args) {
     
    		Squeezer xiaoMing = new XiaoMing();
    		Squeezer father = new Father();
    		Squeezer mather = new Mather();
    		xiaoMing.setSqueezer(father);
    		father.setSqueezer(mather);
    		xiaoMing.handleRequest(new Request("买个糖果",5));
    		xiaoMing.handleRequest(new Request("买个枕头",40));
    		xiaoMing.handleRequest(new Request("买个耳机",260));
    		xiaoMing.handleRequest(new Request("买个Switch",2040));
    	}
    }
    
    /**
     * 	责任链
     * 	小明想买个Switch		但是他没钱,所以向爸爸申请,数额大于100的爸爸没权处理,向掌管财政大权的妈妈申请。
     * 
     **/
    
    //请求类
    class Request{
     
    	private String content;
    	private int money;
    	
    	public Request(){
     }
    	
    	public Request(String content,int money){
     
    		System.out.println(content);
    		this.content = content;
    		this.money = money;
    	}
    	
    	public String getContent() {
     
    		return content;
    	}
    	
    	public void setContent(String content) {
     
    		this.content = content;
    	}
    	
    	public int getMoney() {
     
    		return money;
    	}
    	
    	public void setMoney(int money) {
     
    		this.money = money;
    	}
    }
    
    /**
     * 处理人接口
     * @author Keben
     *
     */
    abstract class Squeezer{
     
    	//低级的处理人内部维护一个其直系上司的引用
    	protected Squeezer squeezer;
    	
    	public void setSqueezer(Squeezer squeezer) {
     
    		this.squeezer = squeezer;
    	}
    	//每个处理人处理的上限,处理不了则向上级抛
    	abstract void handleRequest(Request request);
    }
    
    class XiaoMing extends Squeezer{
     
    	@Override
    	void handleRequest(Request request) {
     
    		if (request.getMoney()>10) {
     
    			System.out.println("自己钱不够,问爸爸要钱");
    			squeezer.handleRequest(request);
    		}else{
     
    			System.out.println("自己钱够买了");
    		}
    	}
    }
    
    class Father extends Squeezer{
     
    	@Override
    	void handleRequest(Request request) {
     
    		if (request.getMoney()>100) {
     
    			System.out.println("爸爸没钱给你买,,我跟你妈妈说一下");
    			squeezer.handleRequest(request);
    		}else{
     
    			System.out.println("爸爸批准了,给你钱");
    		}
    	}
    }
    
    class Mather extends Squeezer{
     
    	@Override
    	void handleRequest(Request request) {
     
    		if (request.getMoney()>1000) {
     
    			System.out.println("太贵了妈妈不准你买");
    		}else{
     
    			System.out.println("不贵妈妈同意了.");
    		}
    	}
    }

命令模式

    命令模式可以将请求发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。命令模式也叫委派模式。
  • 抽象命令类:一般是一个抽象类或接口,在其中声明了用于执行请求的exec()等方法,通过这些方法可以调用请求接收者的相关操作。
     
  • 调用者:调用者即请求发送者,它通过命令对象来执行请求。一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令类之间存在关联关系。在程序运行时可以将一个具体命令对象注入其中,再调用具体命令对象的exec()方法,从而实现间接调用请求接收者的相关操作。
     
  • 请求接收者:接收者执行与请求相关的操作,它具体实现对请求的业务处理。
     
  • 具体命令类:具体命令类是抽象命令类的子类,实现了在抽象命令类中声明的方法,它对应具体的接收者对象,将接收者对象的动作绑定其中。在实现exec()方法时,将调用接收者对象的相关操作。
    public class Demo {
     
    	public static void main(String[] args) {
     
    		Worker worker = new Worker();
    		Role role = new Role();
    		worker.setCmd(new KaoJiCmd(role));
    		worker.startCmd();
    		worker.setCmd(new ZhaJiCmd(role));
    		worker.startCmd();
    	}
    }
    
    /**
     * 角色分为
     * 	服务员	服务员只面对	点餐单	提交订单   订单开始制作
     *  点餐单(命令)		面对		厨师
     * 厨师		面对		点餐单
     */
    
    //抽象命令类
    abstract class Cmd{
     
    	protected Role role;
    	public void setRole(Role role) {
     
    		this.role = role;
    	}
    	public Cmd(Role role) {
     
    		this.role = role;
    	}
    	abstract void exec();
    }
    
    //具体命令类	
    class KaoJiCmd extends Cmd{
     
    	public KaoJiCmd(Role role) {
     
    		super(role);
    	}
    	@Override
    	void exec() {
     
    		role.kaoJi();
    	}
    }
    
    //具体命令类	
    class ZhaJiCmd extends Cmd{
     
    	public ZhaJiCmd(Role role) {
     
    		super(role);
    	}
    	@Override
    	void exec() {
     
    		role.zhaJi();
    	}
    }
    
    //服务员
    class Worker{
     
    	private Cmd cmd;
    	
    	public void setCmd(Cmd cmd) {
     
    		this.cmd = cmd;
    	}
    	public void startCmd(){
     
    		cmd.exec();
    	}
    }
    
    //厨师		请求接受者
    class Role{
     
    	public void kaoJi(){
     
    		System.out.println("kao ji");
    	}
    	
    	public void zhaJi(){
     
    		System.out.println("zha ji");
    	}
    }
  • 命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开
     
  • 每一个命令都是一个操作:请求的一方发出请求,要求执行一个操作;接收的一方收到请求,并执行操作。
     
  • 命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
     
  • 命令模式使请求本身成为一个对象,这个对象和其他对象一样可以被存储和传递
     
  • 命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。

状态模式

    当一个对象状态转换条件判断过于复杂时,把状态的判断逻辑通过判断不同类对象,通过多态自动完成判断的一种设计模式。
  • 状态抽象类
    
    定义一个抽象类以封装与Context的一个特定状态相关的行为,并且内部维护一个Context对象的引用。
  • 状态拥有者
    
        维护一个State子类的实例,这个实例定义当前状态。
  • 状态实现类
    
    每个子类都实现了与Context的一个状态相关的行为。
    public class Test {
     
    	public static void main(String[] args) {
     
    		Context context = new Context();
    		context.setStatus(new KingStatus(context));
    		context.request(10);
    		context.request(30);
    		context.request(20);
    		context.request(50);
    	}
    }
    
    //状态抽象类
    abstract class Status{
     
    	//状态类内部维护拥有者引用,方便修改状态
    	protected Context context;
    	
    	public Status(Context context) {
     
    		// TODO Auto-generated constructor stub
    		this.context = context;
    	}
    	
    	public void setContext(Context context) {
     
    		this.context = context;
    	}
    	
    	abstract void handle(int v);
    }
    
    //状态拥有者
    class Context{
     
    	private Status status;
    	
    	public Context() {
     
    		// TODO Auto-generated constructor stub
    	}
    	
    	public Context(Status status) {
     
    		this.status = status;
    	}
    	
    	public void setStatus(Status status) {
     
    		this.status = status;
    	}
    	
    	public Status getStatus() {
     
    		return status;
    	}
    	
    	public void request(int v){
     
    		status.handle(v);
    	}
    }
    
    class KingStatus extends Status{
     
    	public KingStatus(Context context) {
     
    		super(context);
    	}
    	
    	@Override
    	void handle(int v) {
     
    		if (v>20){
     
    			context.setStatus(new GodStatus(context));
    			context.request(v);
    		}else{
     
    			System.out.println("王者状态!横尸遍野");
    		}
    	}
    }
    
    class GodStatus extends Status{
     
    	public GodStatus(Context context) {
     
    		super(context);
    	}
    	
    	@Override
    	void handle(int v) {
     
    		if(v>40){
     
    			System.out.println("自爆!!!!!");
    		}else if(v<=20){
     
    			context.setStatus(new KingStatus(context));
    			context.request(v);
    		}else{
     
    			System.out.println("战神状态!!无敌模式启动!!!");
    		}
    	}
    }
  • 状态模式和策略模式的区别?
    状态模式是将各个状态所对应的操作分离开来,即对于不同的状态,由不同的子类实现具体操作,不同状态的切换由子类实现,当发现传入参数不是自己这个状态所对应的参数,则自己给Context类切换状态;而策略模式是直接依赖注入到Context类的参数进行选择策略,不存在切换状态的操作。
    
    通俗来说虽然状态模式和策略模式极为相似,但策略模式中策略的更替是外部维护的,而状态模式中状态的更替是内部完成的。

中介者模式

    中介者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使它们可以松散耦合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。例如,租房中介,电话,QQ游戏平台等。
    public class Test {
     
	public static void main(String[] args) {
     
		/**	初始化中介信息  **/
		Intermediary intermediary = new RentalAgency();
		intermediary.getLandlords().add(new Landlord("老王","豪华套房",intermediary));
		intermediary.getLandlords().add(new Landlord("老掌","合租房",intermediary));
		intermediary.getLandlords().add(new Landlord("老比","单间",intermediary));
		intermediary.getLandlords().add(new Landlord("老名","三室一厅",intermediary));
		intermediary.getLandlords().add(new Landlord("老司","三室一厅",intermediary));
		intermediary.getLandlords().add(new Landlord("老达","单人间",intermediary));
		intermediary.getLandlords().add(new Landlord("老哟","一室一厅",intermediary));
		
		/**
		 * 小明最近想租房子,就联系了中介	
		 */
		ILandlord landlord = new Landlord("小明",null, intermediary);
		landlord.sendMessage("单人间");
		
	}
}

//租房中介接口	内部维护房东信息.
abstract class Intermediary{
     
	protected List<ILandlord> landlords = new ArrayList<>();
	public List<ILandlord> getLandlords() {
     
		return landlords;
	}
	abstract void sendMessage(String message,ILandlord landlord);
}

//租房中介实现类
class RentalAgency extends Intermediary{
     

	@Override
	public void sendMessage(String message,ILandlord landlord) {
     
		for (ILandlord iLandlord : landlords) {
     
			if (landlord==iLandlord) {
     
				continue;
			}
			if (iLandlord.getDesc()==null) {
     
				continue;
			}
			if (Objects.equals(message,iLandlord.getDesc())) {
     
				iLandlord.getMessage(message);
				break;
			}
		}
	}
}

//租房客户或房东 接口
abstract class ILandlord{
     
	protected String desc;
	public String getDesc() {
     
		return desc;
	}
	abstract void desc();
	abstract void sendMessage(String message);
	abstract void getMessage(String message);
}

//实现类	,无论是租房客户还是房东内部都要维护中介对象.
class Landlord extends ILandlord{
     
	private String name;
	private Intermediary intermediary;
	
	public Landlord(String name,String desc,Intermediary intermediary) {
     
		this.name = name;
		this.desc = desc;
		this.intermediary = intermediary;
	}
	
	@Override
	public void desc() {
     
		System.out.println(desc);
	}

	@Override
	public void getMessage(String message) {
     
		System.out.println(name+"收到消息");
	}
	
	//租房子.就向中介发送租房信息.
	@Override
	public void sendMessage(String message) {
     
		intermediary.sendMessage(message, this);
	}
}

解释器模式

    把事物高频率的特征和符号都通过解释器来解释,并加以组合处理。
    public class Test {
     
    	public static void main(String[] args) {
     
    		Context context = new Context();
            context.setSum(10);
            List<AbstractExpreesion> list = new ArrayList<>();
            //运行加法三次
            list.add(new PlusExpression());
            list.add(new PlusExpression());
            list.add(new PlusExpression());
            //运行减法两次
            list.add(new MinusExpression());
            list.add(new MinusExpression());
            for (int i = 0; i < list.size(); i++){
     
                AbstractExpreesion expression = list.get(i);
                expression.Interpret(context);
            }
            System.out.println(context.getSum());
    	}
    }
    
    class Context{
     
        private int sum;

        public int getSum() {
     
    		return sum;
    	}
     
        public void setSum(int sum) {
     
    		this.sum = sum;
    	}
    }
    
    // 解释器接口
    interface AbstractExpreesion{
     
       void Interpret(Context context);
    }
    
    //   解释器具体实现类。自加
    class PlusExpression implements AbstractExpreesion{
     
    	@Override
        public void Interpret(Context context){
     
            int sum = context.Sum;
            sum++;
            context.Sum = sum;
        }
    }
    
    //   解释器具体实现类。 自减
    class MinusExpression implements AbstractExpreesion{
     
    	@Override
        public void Interpret(Context context){
     
            int sum = context.Sum;
            sum--;
            context.Sum = sum;
    
        }
    }

访问者模式

    表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
  • 抽象访问者(Visitor):抽象出访问元素的动作
     
  • 具体访问者(ConcreteVisitor):实现访问元素的动作
     
  • 抽象元素(Element):定义一个接受访问的操作,其参数为访问者
     
  • 具体元素(ConcreteElement):实现接受访问操作
     
  • 对象结构类(ObjectStructure):可以枚举元素,并且管理元素
     
  • 客户端(Client) :定义元素集合,然后接受不同访问者的访问
    public class Test {
     
	public static void main(String[] args) {
     
		Blogs blogs = new Blogs();
		blogs.addBlog(new BlogElement("这是第一篇博文"));
		blogs.addBlog(new BlogElement("这是第二篇博文"));
		blogs.addBlog(new BlogElement("这是第三篇博文"));
		blogs.addBlog(new BlogElement("这是第四篇博文"));
		Visitor webVisit = new WebVisitor();
		Visitor wapVisit = new WapVisitor();
		blogs.accept(webVisit);
		blogs.accept(wapVisit);
	}
}

// 抽象访问者(Visitor)
interface Visitor {
     
	void VisitBlog(Element element);
}

// 具体访问者(ConcreteVisitor)
class WebVisitor implements Visitor {
     
	@Override
	public void VisitBlog(Element element) {
     
		System.out.println("通过电脑web网站方式访问Blog:" + element.getBlogName());
	}
}

// 具体访问者(ConcreteVisitor)
class WapVisitor implements Visitor {
     
	@Override
	public void VisitBlog(Element element) {
     
		System.out.println("通过手机wap网站方式访问Blog:" + element.getBlogName());
	}
}

// 抽象元素(Element) 被访问对象
abstract class Element {
     
	public Element(String blogName) {
     
		this.blogName = blogName;
	}

	private String blogName;

	public String getBlogName() {
     
		return blogName;
	}

	public void setBlogName(String blogName) {
     
		this.blogName = blogName;
	}

	abstract public void Accept(Visitor visotr);
}

// 具体元素(ConcreteElement)    具体被访问对象
class BlogElement extends Element {
     
	public BlogElement(String blogName) {
     
		super(blogName);
	}

	@Override
	public void Accept(Visitor visitor) {
     
		visitor.VisitBlog(this);
	}
}

// 对象结构类(ObjectStructure)
class Blogs {
     
	private List<Element> blogList = new ArrayList<Element>();

	public void addBlog(Element element) {
     
		blogList.add(element);
	}

	public void removeBlog(Element element) {
     
		blogList.remove(element);
	}
	
	public void accept(Visitor visitor) {
     
		for (Element e : blogList) {
     
			e.Accept(visitor);
		}
	}
}

最简单的Java设计模式_第1张图片

你可能感兴趣的:(设计模式,Java,设计模式,Java设计模式)