当前位置:   article > 正文

常用设计模式_使用模板方法模式实现出国留学手续设计程序

使用模板方法模式实现出国留学手续设计程序

1. 单例模式

保证一个类仅有一个实例,并提供它的全局访问点
常见写法:
懒汉式

/**
 * 优点:延迟加载,适合单线程操作
 * 缺点:线程不安全,在多线程很容易出现不同步的情况
 */
public class Singleton {
	//持有私有静态实例,防止被引用
	private static Singleton instance = null;
	//私有构造,防止被实例化
	private Singleton () {}
	public static Singleton getInstance() {
		if (instance==null) {
			instance = new Singleton();
		}
		return instance;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

双重线程检查模式

/**
 * 优点:延迟加载,线程安全
 * 缺点:写法复杂,不简洁
 */
public class Singleton {
	private static volatile Singleton sInst = null;
	//私有构造,防止被实例化
	private Singleton () {}
	public static Singleton getInstance() {
		//创建临时变量
		Singleton inst = sInst;
		if (inst==null) {
			synchronized (Singleton.class) {
				inst = sInst;
				if (inst==null) {
					inst = new Singleton();
					sInst = inst;
				}
			}
		}
		return inst;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

饿汉式

/**
 * 优点:延迟加载,线程安全(java中class加载时互斥的),减少了内存小号,推荐使用内部类方式
 */
public class Singleton {
	//内部类实现单例,延迟加载,减少内存开销
	private static class SingletonHolder {
		private static Singleton instance = new Singleton();
	}
	private Singleton() {}
	public static Singleton getInstance() {
		return SingletonHolder.instance;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.工厂模式

3.建造模式

是一种对象构建的设计模式,它可以将负责对象的构建过程抽象出来,使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象
建造模式结构图
为何使用
是为了将构建复杂对象的过程和它的部件解耦
如何使用

//需要一个接口,它定义如何创建复杂对象的各个部件
public interface Builder {
	//创建部件A
	void buildPartA();
	//创建部件B
	void buildPartB();
	//创建部件C
	void buildPartC();
	//从而实现了解耦过程和部件
	Product getResult();
}
//构建最后的复杂对象
public class Director {
    private Builder builder;
    public Director( Builder builder ) {
        this.builder = builder;
   }
   // 将部件partA partB partC最后组成复杂对象
   //这里是将车轮 方向盘和发动机组装成汽车的过程
    public void construct() {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
    }
}
//具体实现,明确需要创建的东西
public class ConcreteBuilder implement Builder {
	Part partA, partB, partC;
	public void buildPartA() {
		//具体实现
	}
	public void buildPartB() {
		//具体实现
	}
	public void buildPartC() {
		//具体实现
	}
	public Product getResult() {
		//返回组装结果
	}
}
//复杂对象:产品Product
public interface Product{}
//复杂对象的部件
public interface Part{}

public void main(String[] args) {
	ConcreteBuilder builder = new ConcreteBuilder();
	Director director = new Director(builder);
	director.construct();
	Product product = builder.getResult();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

4.观察者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同事监听某一主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。观察者模式又叫发布-订阅(Publish/Subscribe)模式
观察者模式结构图
模式的结构
观察者模式的主要角色如下。

  • 抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
  • 具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
  • 抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
  • 具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
    如何使用
public class ObserverPattern
{
    public static void main(String[] args)
    {
        Subject subject=new ConcreteSubject();
        Observer obs1=new ConcreteObserver1();
        Observer obs2=new ConcreteObserver2();
        subject.add(obs1);
        subject.add(obs2);
        subject.notifyObserver();
    }
}
//抽象目标
abstract class Subject
{
    protected List<Observer> observers=new ArrayList<Observer>();
    //增加观察者方法
    public void add(Observer observer)
    {
        observers.add(observer);
    }
    //删除观察者方法
    public void remove(Observer observer)
    {
        observers.remove(observer);
    }
    public abstract void notifyObserver(); //通知观察者方法
}
//具体目标
class ConcreteSubject extends Subject
{
    public void notifyObserver()
    {
        System.out.println("具体目标发生改变...");
        System.out.println("--------------");

        for(Object obs:observers)
        {
            ((Observer)obs).response();
        }

    }
}
//抽象观察者
interface Observer
{
    void response(); //反应
}
//具体观察者1
class ConcreteObserver1 implements Observer
{
    public void response()
    {
        System.out.println("具体观察者1作出反应!");
    }
}
//具体观察者1
class ConcreteObserver2 implements Observer
{
    public void response()
    {
        System.out.println("具体观察者2作出反应!");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

何时适用

  • 当一个抽象模型有两个方面,其中一个方面依赖另一个方面。将二者封装在独立的对象中可以使他们各自独立地改变和复用
  • 当对一个对象的改变需要同时改变其他对象,而不知道具体由多少对象有待改变
  • 当一个对象必须通知其他对象,而它又不能假定其他对象是谁。让耦合的双方都依赖于抽象,而不是依赖于具体

模式的扩展
在Java中,通过java.util.Observable类和java.util.Observer接口定义了观察者模式,只要实现他们的子类就可以编写观察者模式

  1. Observable类:抽象目标类,它有一个Vector向量
    • addObserver(Observer o)方法:用于将新的观察者对象添加到向量中
    • notifyObservers(Observer o)方法:调用向量中的所有观察者的update,通常越晚加入向量的观察者越先得到通知
    • setChange()方法:用来设置一个boolean类型的内部标志位,注明对象发生了变化。当为真时,notifyObservers()才会通知观察者
  2. Observer接口:抽象观察者
/**
 * @Desc:
 * @Author: zhouben
 * @Date:2019/7/3 10:28
 */
public class CrudeOilFutures {

    public static void main(String[] args) {
        OilFutures oil = new OilFutures();
        Observer bull = new Bull(); //多方
        Observer bear = new Bear();   //空方
        oil.addObserver(bull);
        oil.addObserver(bear);
        oil.setPrice(10);
        oil.setPrice(-8);
    }
}
/**
 * @Desc: 目标类:原油期货
 * @Author: zhouben
 * @Date:2019/7/3 10:23
 */
public class OilFutures extends Observable {

    private float price;

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        //设置内部标志位,注明数据发生变化
        super.setChanged();
        //通知观察者价格变了
        super.notifyObservers(price);
        this.price = price;
    }
}
/**
 * @Desc: 具体观察者:多方
 * @Author: zhouben
 * @Date:2019/7/3 10:25
 */
public class Bull implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        float price = ((Float) arg).floatValue();
        if (price > 0) {
            System.out.println("油价上涨"+price+"元,多方高兴了!");
        } else {
            System.out.println("油价下跌"+(-price)+"元,多方伤心了!");
        }
    }
}
/**
 * @Desc: 具体观察者:空方
 * @Author: zhouben
 * @Date:2019/7/3 10:25
 */
public class Bear implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        float price = ((Float) arg).floatValue();
        if (price > 0) {
            System.out.println("油价上涨"+price+"元,空方伤心了!");
        } else {
            System.out.println("油价下跌"+(-price)+"元,空方高兴了!");
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73

5.适配器模式

适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法再一起工作时的两个类都能在一起工作
类适配器模式
适配器模式结构图
从上图可以看出,Adaptee类并没有samepleOperation2()方法,而客户端则期待这个方法。为使客户端能够使用Adaptee类,提供一个中间环节,即类Adapter,把Adaptee的API与target类的API衔接起来

public interface Target {
    /**
     * 这是源类Adaptee也有的方法
     */
    public void sampleOperation1(); 
    /**
     * 这是源类Adapteee没有的方法
     */
    public void sampleOperation2(); 
}

public class Adaptee {
    public void sampleOperation1(){}
}

public class Adapter extends Adaptee implements Target {
    /**
     * 由于源类Adaptee没有方法sampleOperation2()
     * 因此适配器补充上这个方法
     */
    @Override
    public void sampleOperation2() {
        //写相关的代码
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

对象适配器模式
对象适配器模式
从上图可以看出,Adaptee类并没有sampleOperation2()方法,而客户端则期待这个方法。为使客户端能够使用Adaptee类,需要提供一个包装(Wrapper)类Adapter。这个包装类包装了一个Adaptee的实例,从而此包装类能够把Adaptee的API与Target类的API衔接起来。Adapter与Adaptee是委派关系,这决定了适配器模式是对象的。

public interface Target {
    /**
     * 这是源类Adaptee也有的方法
     */
    public void sampleOperation1(); 
    /**
     * 这是源类Adapteee没有的方法
     */
    public void sampleOperation2(); 
}

public class Adaptee {
    public void sampleOperation1(){}
}

public class Adapter {
    private Adaptee adaptee;
    public Adapter(Adaptee adaptee){
        this.adaptee = adaptee;
    }
    /**
     * 源类Adaptee有方法sampleOperation1
     * 因此适配器类直接委派即可
     */
    public void sampleOperation1(){
        this.adaptee.sampleOperation1();
    }
    /**
     * 源类Adaptee没有方法sampleOperation2
     * 因此由适配器类需要补充此方法
     */
    public void sampleOperation2(){
        //写相关的代码
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

6. 装饰者模式

装饰(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些指责(即增加其额外功能)的模式,它属于对象结构型模式

优点:

  1. 采用装饰模式扩展对象的功能比采用继承方式更加灵活
  2. 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合

缺点: 增加了许多子类,过度使用会使程序变得复杂

模式的结构

  1. 抽象构件角色(Component):定义一个抽象接口以规范准备接收附加责任的对象
  2. 具体构件角色(ConcreteComponent):实现抽象构件,通过装饰角色为其添加一些职责
  3. 抽象装饰角色(Decorator):继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能
  4. 具体装饰角色(ConcreteDecorator):实现抽象装饰的相关方法,并给具体构件对象添加附加的责任

装饰模式的结构图:
在这里插入图片描述
模式的实现


public class MorriganAensland {
    public static void main(String[] args) {
        Morrigan m0 = new Original();
        m0.display();
        Morrigan m1 = new Succubus(m0);
        m1.display();
        Morrigan m2 = new Girl(m0);
        m2.display();
    }
}
/**
 * 抽象构件角色
 */
public interface Morrigan {
    public void display();
}
/**
 * @Desc: 具体构件角色
 * @Author: zhouben
 * @Date:2019/7/2 10:19
 */
public class Original extends JFrame implements Morrigan {
    private String t = "Morrigan0.jpg";
    public Original() {
        super("《恶魔战士》中的莫莉卡·安斯兰");
    }

    public void setImage(String t) {
        this.t = t;
    }

    @Override
    public void display() {
        /*this.setLayout(new FlowLayout());
        JLabel l1=new JLabel(new ImageIcon("com/zben/decorator/"+t));
        this.add(l1);
        this.pack();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);*/
        System.out.println("具体构件角色....Morrigan0.jpg");
    }
}

/**
 * @Desc: 抽象装饰角色
 * @Author: zhouben
 * @Date:2019/7/2 10:24
 */
public class Changer implements Morrigan {

    Morrigan m;

    public Changer(Morrigan m) {
        this.m = m;
    }

    @Override
    public void display() {
        m.display();
    }
}
/**
 * @Desc: 具体装饰角色:女妖
 * @Author: zhouben
 * @Date:2019/7/2 10:26
 */
public class Succubus extends Changer {

    public Succubus(Morrigan m) {
        super(m);
    }

    @Override
    public void display() {
        setChanger();
        super.display();
    }

    private void setChanger() {
        ((Original)super.m).setImage("Morrigan1.jpg");
        System.out.println("Morrigan1");
    }
}
/**
 * @Desc: 具体装饰角色:少女
 * @Author: zhouben
 * @Date:2019/7/2 10:26
 */
public class Girl extends Changer {

    public Girl(Morrigan m) {
        super(m);
    }

    @Override
    public void display() {
        setChanger();
        super.display();
    }

    private void setChanger() {
        ((Original)super.m).setImage("Morrigan2.jpg");
        System.out.println("Morrigan2");
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107

7. 代理模式

代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为对象和目标对象之间的中介
优点

  1. 代理模式在客户端与目标对象之间起到了一个中介作用和保护目标的作用
  2. 代理对象可以扩展目标对象的功能
  3. 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度

缺点

  1. 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢
  2. 增加了系统的复杂度

模式的结构
抽象主题(Subject):通过接口或抽象类声明真实主题和代理对象实现的业务方法
真实主题(RealSubject):实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
代理(Proxy):提供了与真实主题相同的接口,其内部含有对真实主题的引用
在这里插入图片描述
模式的实现


public class WySpecialProxy {
    public static void main(String[] args) {
        Sgproxy sgproxy = new Sgproxy();
        sgproxy.display();
    }
}
/**
 * 抽象主题
 */
public interface Specialty {
    public void display();
}

/**
 * @Desc: 真实主题
 * @Author: zhouben
 * @Date:2019/7/2 11:28
 */
public class WySpecialty extends JFrame implements Specialty {

    public WySpecialty() {
        super("韶关代理婺源特产测试");
        this.setLayout(new GridLayout(1,1));
        JLabel l1=new JLabel(new ImageIcon("D:\\idea-project\\test\\java-design\\src\\main\\resources\\WuyuanSpecialty.jpg"));
        this.add(l1);
        this.pack();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public void display() {
        this.setVisible(true);
    }
}

/**
 * @Desc:代理类
 * @Author: zhouben
 * @Date:2019/7/2 11:31
 */
public class Sgproxy implements Specialty {

    private WySpecialty realSubject=new WySpecialty();
    @Override
    public void display() {
        preRequest();
        realSubject.display();
        postRequest();
    }

    public void preRequest() {
        System.out.println("韶关代理婺源开始。。。");
    }
    public void postRequest() {
        System.out.println("韶关代理婺源结束。。。");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

8. 原型模式

定义
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的心对象。
模式的结构

  1. 抽象原型类:规定了具体原型对象必须实现的接口
  2. 具体原型类:实现抽象原型类的clone()方法,它是可被复制的对象
  3. 访问类:使用具体原型类的clone()方法来复制对象
    在这里插入图片描述
    模式的实现
    原型模式的克隆分为浅克隆和深克隆,java中Object类提供了浅克隆的clone()方法,具体原型类只要实现Cloneable接口就可实现浅克隆

public class ProtoTypeCitation {
    public static void main(String[] args) throws CloneNotSupportedException {
        Citation obj1 = new Citation("张三", "同学:在2016学年第一学期中表现优秀,被评为三好学生。","韶关学院");
        obj1.display();
        Citation obj2 = (Citation)obj1.clone();
        obj2.setName("李四");
        obj2.display();
    }
}

public class Citation implements Cloneable {
    private String name;
    private String info;
    private String college;

    public Citation(String name, String info, String college) {
        this.name = name;
        this.info = info;
        this.college = college;
        System.out.println("奖状创建成功!");
    }

    public void display() {
        System.out.println(name + info + college);
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        System.out.println("奖状拷贝成功!");
        return (Citation)super.clone();
    }

    public String getName() {
        return name;
    }

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

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public String getCollege() {
        return college;
    }

    public void setCollege(String college) {
        this.college = college;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

原型模式的应用场景

  1. 对象之间相同或相似,即只是个别的几个属性不同的时候
  2. 对象的创建过程比较麻烦,但复制比较简单的时候

9. 模板方法模式

定义:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤

优点

  1. 封装了不变得部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展
  2. 它在父类中提取了公共的部分代码,以便于代码复用
  3. 部分方法是由子类实现的,因此可以通过扩展方式增加相应的功能,符合开闭原则

模式的结构

  • 抽象类:负责给出一个算法的轮廓和骨架。由一个模板方法和若干基本方法构成
  • 具体子类:实现抽象类中所定义的抽象方法和钩子方法。
    在这里插入图片描述
    模式的实现
/**
 * @Desc: 用模板方法模式实现出国留学手续设计程序。
 * 分析:出国留学手续一般经过以下流程:索取学校资料,提出入学申请,办理因私出国护照、出境卡和公证,申请签证,
 * 体检、订机票、准备行装,抵达目标学校等,其中有些业务对各个学校是一样的,但有些业务因学校不同而不同,
 * 所以比较适合用模板方法模式来实现。
 * @Author: zhouben
 * @Date:2019/7/2 14:44
 */
public class StudyAbroadProcess {
    public static void main(String[] args) {
        StudyAbroad studyAbroad = new StudyInAmerica();
        studyAbroad.templateMethod();
    }
}

/**
 * @Desc: 抽象类:出国留学
 * @Author: zhouben
 * @Date:2019/7/2 14:35
 */
public abstract class StudyAbroad {
    //模板方法
    public void templateMethod() {
        lookingForSchool(); //索取学校资料
        applyForEnrol();    //入学申请
        applyForPassport(); //办理因私出国护照、出境卡和公证
        applyForVisa();     //申请签证
        readyGoAbroad();    //体检、订机票、准备出行
        arriving();         //抵达
    }

    protected abstract void arriving();

    protected abstract void applyForEnrol();

    protected abstract void lookingForSchool();

    private void readyGoAbroad() {
        System.out.println("五.体检、订机票、准备行装:");
        System.out.println("  1)进行身体检查、免疫检查和接种传染病疫苗;");
        System.out.println("  2)确定机票时间、航班和转机地点。");
    }

    private void applyForVisa() {
        System.out.println("四.申请签证:");
        System.out.println("  1)准备申请国外境签证所需的各种资料,包括个人学历、成绩单、工作经历的证明;个人及家庭收入、资金和财产证明;家庭成员的关系证明等;");
        System.out.println("  2)向拟留学国家驻华使(领)馆申请入境签证。申请时需按要求填写有关表格,递交必需的证明材料,缴纳签证。有的国家(比如美国、英国、加拿大等)在申请签证时会要求申请人前往使(领)馆进行面试。");
    }

    private void applyForPassport() {
        System.out.println("三.办理因私出国护照、出境卡和公证:");
        System.out.println("  1)持录取通知书、本人户口簿或身份证向户口所在地公安机关申请办理因私出国护照和出境卡。");
        System.out.println("  2)办理出生公证书,学历、学位和成绩公证,经历证书,亲属关系公证,经济担保公证。");
    }
}

/**
 * @Desc:具体子类:美国留学
 * @Author: zhouben
 * @Date:2019/7/2 14:43
 */
public class StudyInAmerica extends StudyAbroad {
    @Override
    protected void arriving() {
        System.out.println("六.抵达目标学校:");
        System.out.println("  1)安排住宿;");
        System.out.println("  2)了解校园及周边环境。");
    }

    @Override
    protected void applyForEnrol() {
        System.out.println("二.入学申请:");
        System.out.println("  1)填写报名表;");
        System.out.println("  2)将报名表、个人学历证明、最近的学习成绩单、推荐信、个人简历、托福或雅思语言考试成绩单等资料寄往所申请的学校;");
        System.out.println("  3)为了给签证办理留有充裕的时间,建议越早申请越好,一般提前1年就比较从容。");
    }

    @Override
    protected void lookingForSchool() {
        System.out.println("一.索取学校以下资料:");
        System.out.println("  1)对留学意向国家的政治、经济、文化背景和教育体制、学术水平进行较为全面的了解;");
        System.out.println("  2)全面了解和掌握国外学校的情况,包括历史、学费、学制、专业、师资配备、教学设施、学术地位、学生人数等;");
        System.out.println("  3)了解该学校的住宿、交通、医疗保险情况如何;");
        System.out.println("  4)该学校在中国是否有授权代理招生的留学中介公司?");
        System.out.println("  5)掌握留学签证情况;");
        System.out.println("  6)该国政府是否允许留学生合法打工?");
        System.out.println("  8)毕业之后可否移民?");
        System.out.println("  9)文凭是否受到我国认可?");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90

10. 策略模式

定义:策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法实现分割开来,并委派给不同的对象对这些算法进行管理
优点

  1. 避免使用多重条件语句
  2. 提供一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码
  3. 提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的
  4. 提供了对开闭原则的完美支持,可以在不修改源代码的情况下,灵活增加新算法
  5. 把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现二者分离

模式的结构

  1. 抽象策略类:定义一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法
  2. 具体策略类:实现了抽象策略定义的接口,提供具体的算法实现
  3. 环境类:持有一个策略类的引用,最终给客户端调用

在这里插入图片描述

/**
 * @Desc:策略模式在“大闸蟹”做菜中的应用。
 *
 * 分析:关于大闸蟹的做法有很多种,我们以清蒸大闸蟹和红烧大闸蟹两种方法为例,介绍策略模式的应用。
 * @Author: zhouben
 * @Date:2019/7/2 17:28
 */
public class StrategyMain {

    public static void main(String[] args) {

        Kitchen kitchen = new Kitchen(new BraisedCrabs());
        kitchen.cookingMethod();
    }
}

/**
 * 抽象策略:
 */
public interface CrabCooking {

    //做菜方法
    public void cookingMethod();
}
/**
 * @Desc: 具体策略类:红烧大闸蟹
 * @Author: zhouben
 * @Date:2019/7/2 17:24
 */
public class BraisedCrabs implements CrabCooking {

    @Override
    public void cookingMethod() {
        System.out.println("红烧大闸蟹");
    }
}
/**
 * @Desc: 具体策略类:清蒸大闸蟹
 * @Author: zhouben
 * @Date:2019/7/2 17:24
 */
public class SteamedCrabs implements CrabCooking {

    @Override
    public void cookingMethod() {
        System.out.println("清蒸大闸蟹");
    }
}
/**
 * @Desc: 环境类:厨房
 * @Author: zhouben
 * @Date:2019/7/2 17:25
 */
public class Kitchen {

    private CrabCooking strategy;   //抽象策略

    public Kitchen(CrabCooking strategy) {
        this.strategy = strategy;
    }

    public void cookingMethod() {
        strategy.cookingMethod();
    }

    public CrabCooking getStrategy() {
        return strategy;
    }

    public void setStrategy(CrabCooking strategy) {
        this.strategy = strategy;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/525911
推荐阅读
相关标签
  

闽ICP备14008679号