设计模式

原型模式

  • Prototype模式是一种对象创建型模式,它采用赋值原型对象的方法来创建对象的实例
  • 使用Prototyp模式创建的实例,具有与原型一样的数据
package com.Test.DesignPattern;


public class Clone{
    String Name;
    int age;
    String address;
    public String getName() {
        return Name;
    }
    public void setName(String name) {
        Name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
}
  • 创建类,有名字,地址和年龄的属性
package com.Test.DesignPattern;

public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Clone clone = new Clone();
        clone.setAddress("Moon");
        clone.setName("GuXue");
        clone.setAge(18);

        Clone clone2 = new Clone();
        clone2.setAddress("Moon");
        clone2.setName("Leave");
        clone2.setAge(18);
    }
}

创建了两个Clone对象,仅仅只有名字不同罢了,但是clone2却不能直接使用clone中的地址和年龄

  • 由原型对象自身创建目标对象, 也就是说,对象创建这一动作发自原型对象本身
  • 目标对象是原型对象的一个克隆。也就是说,通过Prototype模式创建的对象不仅仅与原型对象具有相同的结构,还具有相同的值
  • 根据对象克隆深度层次不同,有浅克隆和深度克隆
package com.Test.DesignPattern;


public class Clone implements Cloneable {
    String Name;
    int age;
    String address;
    public String getName() {
        return Name;
    }
    public void setName(String name) {
        Name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public Clone clone() {
        try {
            return (Clone) super.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }
}
  • 这里我们通过实现接口的方式,实现Cloneable接口,返回一个具有相同值的对象
  • 这个接口是为了声明该类是可以克隆的,其内部并没有什么方法或属性
package com.Test.DesignPattern;

public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Clone clone = new Clone();
        clone.setAddress("Moon");
        clone.setName("GuXue");
        clone.setAge(18);

        Clone clone2 = clone.clone();
        clone2.setName("Leave");
    }
}

这里在Clone中添加可以被作为引用的对象List

package com.Test.DesignPattern;

import java.util.List;

public class Clone implements Cloneable {
    String Name;
    int age;
    String address;
    List<String> friends;
    public List<String> getFriends() {
        return friends;
    }
    public void setFriends(List<String> friends) {
        this.friends = friends;
    }
    public String getName() {
        return Name;
    }
    public void setName(String name) {
        Name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public Clone clone() {
        try {
            return (Clone) super.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }
}
  • 书写测试代码
package com.Test.DesignPattern;

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

public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Clone clone = new Clone();
        clone.setAddress("Moon");
        clone.setName("GuXue");
        clone.setAge(18);

        List<String> friends = new ArrayList<String>();
        friends.add("KK");
        friends.add("Jinmu");
        friends.add("DongDong");
        clone.setFriends(friends);
        Clone clone2 = clone.clone();

        System.out.println("clone's friends:");
        System.out.println(clone.getFriends());
        System.out.println("clone2's friends:");
        System.out.println(clone2.getFriends());

        friends.add("Maya");
        clone.setFriends(friends);
        System.out.println("------------------------");

        System.out.println("clone's friends:");
        System.out.println(clone.getFriends());
        System.out.println("clone2's friends:");
        System.out.println(clone2.getFriends());
    }
}
clone's friends:
[KK, Jinmu, DongDong]
clone2's friends:
[KK, Jinmu, DongDong]
------------------------
clone's friends:
[KK, Jinmu, DongDong, Maya]
clone2's friends:
[KK, Jinmu, DongDong, Maya]
  • 可以发现,引用类型的clone指向的同一个对象
  • 这样的一个clone就是一个浅度克隆·

深度克隆

public Clone clone() {
    try {
        Clone clone = (Clone) super.clone();
        List<String> newFriends = new ArrayList<String>();
        for (String friendString : this.getFriends()) {
            newFriends.add(friendString);
        }
        clone.setFriends(newFriends);
        return clone;
    } catch (CloneNotSupportedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return null;
    }
}
clone's friends:
[KK, Jinmu, DongDong]
clone2's friends:
[KK, Jinmu, DongDong]
------------------------
clone's friends:
[KK, Jinmu, DongDong, Maya]
clone2's friends:
[KK, Jinmu, DongDong]
  • 原型模型应用场景
    • 在创建对象的时候,我们不只希望被创建对象集成其基类基本结构,还希望集成原型对象的数据
    • 希望目标对象的修改不影响既有的原型对象(深度克隆完全不影响)
    • 隐藏克隆操作的细节。很多时候,对对象本身的克隆需要涉及到类本身的数据细节。

建造者模式

  • Builder模式也叫建造者模式或者生成器模式
  • Builder模式是一种对象创建型模式之一。
  • 用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象
  • 通过子类继承和重载的方式,动态地创建具有复合属性的对象
package com.Test.DesignPattern;

public class House {
    private String floor;//地板
    private String wall;// 墙
    private String top;// 屋顶
    public String getFloor() {
        return floor;
    }
    public void setFloor(String floor) {
        this.floor = floor;
    }
    public String getWall() {
        return wall;
    }
    public void setWall(String wall) {
        this.wall = wall;
    }
    public String getTop() {
        return top;
    }
    public void setTop(String top) {
        this.top = top;
    }
}

创建一个House类

package com.Test.DesignPattern;


public class Main {

    public static void main(String[] args) {
        House house = new House();
        house.setFloor("地板");
        house.setTop("屋顶");
        house.setWall("墙");
    }
}

由客户创建House对象

package com.Test.DesignPattern;


public interface HouseBuilder {
    public void makeFloor();
    public void makeWall();
    public void makeHouseTop();
    public House getHouse();
}

创建创建House的接口

package com.Test.DesignPattern;

public class PingFangBuilder implements HouseBuilder {
    // 修建平房的工程队
    House house = new House();
    @Override
    public void makeFloor() {
        // TODO Auto-generated method stub
        house.setFloor("平房的地板");
    }

    @Override
    public void makeWall() {
        // TODO Auto-generated method stub
        house.setWall("平房的地板");
    }

    @Override
    public void makeHouseTop() {
        // TODO Auto-generated method stub
        house.setTop("平房的屋顶");
    }

    @Override
    public House getHouse() {
        // TODO Auto-generated method stub
        return house;
    }

}

这是一个创建平房的House的类

package com.Test.DesignPattern;

public class GongYuBuilder implements HouseBuilder{
    private House house;
    @Override
    public void makeFloor() {
        // TODO Auto-generated method stub
        house.setFloor("公寓的地板");
    }

    @Override
    public void makeWall() {
        // TODO Auto-generated method stub

        house.setWall("公寓的墙");
    }

    @Override
    public void makeHouseTop() {
        // TODO Auto-generated method stub
        house.setTop("公寓的房顶");
    }

    @Override
    public House getHouse() {
        // TODO Auto-generated method stub
        return house;
    }
}

这是创建公寓的House的类

  • 通过PingFangBuilder,可以由工程队创建House对象而不用用户创建
HouseBuilder houseBuilder = new PingFangBuilder();
houseBuilder.makeFloor();
houseBuilder.makeHouseTop();
houseBuilder.makeWall();
House house1 = houseBuilder.getHouse();

HouseBuilder houseBuilder2 = new GongYuBuilder();
houseBuilder.makeFloor();
houseBuilder.makeHouseTop();
houseBuilder.makeWall();
House house2 = houseBuilder.getHouse();

但是弊端又来了,还是必须由用户去调用工程队的所有make函数

设计模式_第1张图片

  • 新建一个设计师对象Director,由Director来控制工程队做事
package com.Test.DesignPattern;

public class HouseDirector {
    private HouseBuilder houseBuilder;

    public HouseDirector(HouseBuilder builder) {
        this.houseBuilder = builder;
    }

    public void makeHouse() {
        this.houseBuilder.makeFloor();
        this.houseBuilder.makeHouseTop();
        this.houseBuilder.makeWall();
    }
}
public class Main {

    public static void main(String[] args) {
        HouseBuilder houseBuilder = new PingFangBuilder();
        HouseBuilder gongyuBuilder = new GongYuBuilder();
        HouseDirector houseDirector = new HouseDirector(houseBuilder);
        // 创建一个平房
        houseDirector.makeHouse();
        House house = houseBuilder.getHouse();
        System.out.println(house.getFloor());
        System.out.println(house.getTop());
        System.out.println(house.getWall());

        // 创建一个公寓
        HouseDirector houseDirector2 = new HouseDirector(gongyuBuilder);
        House house2 = houseBuilder2.getHouse();
        System.out.println(house2.getFloor());
        System.out.println(house2.getTop());
        System.out.println(house2.getWall());
    }
}

不难发现,对于多种HouseBuilder的实现类。使用一个Dirctor来调用方法显得更快,代码复用更高
每个House都由用户创建,代码量最高,需求变换是几乎全部都要修改
使用HouseBuilder代码量中等,需求变化时较麻烦
使用Director,代码量最少,需要改变时仅修改Director传入的HouseBuilder就可以了

  • 建造者模式应用场景
    • 对象的创建:builder模式是为对象的创建而设计的模式
    • 创建的是一个复合对象:被创建的对象为一个具有复合属性的复合对象
    • 关注对象创建的各个部分的创建过程:不同的工厂(这里是指Builder生成器)对产品属性有不同的创建方法

装饰模式

  • 装饰(Decorator)模式又叫包装模式
  • 通过一种对客户端透明的方式来扩展对象的功能,是继承关系的替换方案
现代汽车都能跑
但是随着时代发展,未来汽车也许能飞
package com.Test.DesignPattern;

public class RunCar {
    public void run() {
        System.out.println("跑");
    }
    public void fly() {
        System.out.println("飞");
    }
    public void swim() {
        System.out.println("游");
    }
    public void show(){
        System.out.println("拥有的功能");
        this.run();
        this.fly();
        this.swim();
    }
}

但是 不是所有的Car 都以 飞,跑,游,所以直接创建一个类具有这三个特性是不合适的

package com.Test.DesignPattern;

public interface Car {
    public void show();
    public void run();// 一般车都可以跑
}

创建Car的接口,show为展示功能,一般车都能跑,故加上run

package com.Test.DesignPattern;

public class Car implements Car {

    @Override
    public void show() {
        // TODO Auto-generated method stub
        this.run();
    }
    public void run() {
        System.out.println("可以跑");
    }
}

只能跑的车

package com.Test.DesignPattern;

public class FlyCar implements Car {

    @Override
    public void show() {
        // TODO Auto-generated method stub
        this.fly();
        this.run();
    }
    public void fly() {
        System.out.println("可以飞");
    }
    public void run() {
        System.out.println("可以跑");
    }
}

在run之上,可以飞的车

package com.Test.DesignPattern;

public class SwimCar implements Car {

    @Override
    public void show() {
        // TODO Auto-generated method stub
        this.run();
        this.swim();
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("可以跑");
    }
    public void swim() {
        System.out.println("可以游");
    }
}

在run之上可以游的车

  • 通过上面的两个类,可以对不同的车创建不同的对象
  • 通过添加子类的方法来添加功能
  • 但是,如果再加几个功能呢?每个功能都写一个类的话岂不是很麻烦?
  • 这里我们使用装饰模式

设计模式_第2张图片

  • Component:组件,相当于这里的Car
  • ConcreteComponent:实体组件,相当于这里实现的FlyCar,SwimCar
  • Decorator:装饰的抽象类,
  • ConcreteDecoratorA,B:通过这两个类 给Decorator添加功能
package com.Test.DesignPattern;


public abstract class CarDecorator implements Car {
    private Car car;
    public Car getCar() {
        return car;
    }
    public CarDecorator(Car car) {
        this.car = car;
    }

    public abstract void show(); 
}

抽象的装饰类,实现Car接口是为了能够多重装饰

package com.Test.DesignPattern;

public class SwimCarDecorator extends CarDecorator {

    public SwimCarDecorator(Car car) {
        super(car);
        // TODO Auto-generated constructor stub
    }

    public void show() {
        this.getCar().show(); // 先展示出以前的功能
        this.swim(); // 再添加新的功能
    }

    public void swim() {
        System.out.println("可以游");
    }

    public void run() {
        // TODO Auto-generated method stub
    }
}

添加游泳能力的Car

package com.Test.DesignPattern;

public class FlyCarDecorator extends CarDecorator {
    public FlyCarDecorator(Car car) {
        super(car);
    }

    public void show() {
        this.getCar().show();
        this.fly();
    }

    public void fly() {
        System.out.println("飞");
    }

    public void run() {
        // TODO Auto-generated method stub

    }
}

添加飞能力的Car

public class Main {

    public static void main(String[] args) {
        Car Car = new RunCar();
        CarDecorator carDecorator = new FlyCarDecorator(Car);
        carDecorator.show();
        CarDecorator carDecorator2 = new SwimCarDecorator(carDecorator);
        carDecorator2.show();
    }
}

先创建一个Car,然后给Car添加上飞的功能
因为这里的carDecorator是CarDecorator类型,而SwimCardecorator的传入参数是Car类型,所以CarDecorator需要实现Car接口,以实现多重装饰

  • 抽象组件角色:一个抽象接口,是被装饰类和装饰类的父接口(这里的CarDecorator)
  • 具体组件角色:为抽象组件的实现类(这里的RunCar)
  • 抽象装饰角色:包含一个组件的引用,并定义了抽象组件一致的接口
  • 具体装饰角色:为抽象装饰角色的实现类。负责具体的装饰(这里的FlyCarDecorator)

策略模式

  • Strategy模式,也叫策略模式。是行为模式之一
  • 它对一系列的算法加以封装,为所有算法定义一个抽象的算法接口,并通过继承该抽象算法接口对所有的算法加以封装和实现
  • 具体的算法选择交由客户端决定(策略)
  • Strategy模式主要用于平滑地处理算法的切换

设计模式_第3张图片

package com.Test.DesignPattern;

public class MD5Strategy implements Strategy {

	@Override
	public void encrypt() {
		// TODO Auto-generated method stub
		System.out.println("MD5的加密");
	}

}

策略抽象接口类

package com.Test.DesignPattern;

public class MDSStrategy implements Strategy{

	@Override
	public void encrypt() {
		// TODO Auto-generated method stub
		System.out.println("非MD5的实现,执行MDS加密");
	}

}

具体实现的算法1

package com.Test.DesignPattern;

public class Context {
	
	private Strategy strategy;
	public Context(Strategy strategy) {
		this.strategy = strategy;
	}
	
	public void encrypt() {
		this.strategy.encrypt();
	}
}

具体实现的算法2

Context context = new Context(new MD5Strategy);
context.encrypy();

使用策略模式封装一层Context,对外使用的方法都是encrypy
若要修改实现算法,则传入Context的参数可以修改为 new MDSStrategy

  • Strategy:策略(算法)抽象

  • ConcreteStrategy:各种策略(算法)的具体实现

  • Context:策略的外部封装类,或者说策略的容器类。根据不同策略执行不同的行为。策略由外部环境决定

  • 优点:

    • 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。乔当使用继承可以把公共的代码移到父类里面,从而避免重复的代码
    • 策略模式提供类可以替代继承关系的方法。继承可以处理多种算法或行为。如果不使用策略模式,那么使用算法或行动的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样依赖算法或行为的使用者就和行为本身会在一起。决定使用哪种算法或采取哪种行为的逻辑就和算法或行为的逻辑混在一起,从而不能达到独立烟花。继承使得动态改变算法或行为变得不可能
    • 使用策略模式以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的路基混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始落后
      -缺点:
      • 客户端必须知道所有的策略类,并自行决定使用哪一种策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况下
      • 策略模式造成很多的策略类。有时候可以通过把依赖与环境的状态保存到客户端里,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。换言之,可以使用享元模式来介绍对象的数量

观察者模式

  • Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态
  • Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的对象之间保持同步状态
  • Subject(被观察者)
    • 被观察的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。Subject需要维持(添加,删除,通知)一个观察者对象的队列列表
  • ConcreteSubject
    • 被观察者的具体实现。包含一些基本的属性状态及其他操作
  • Observer(观察者)
    • 接口或抽象类。当Subject的状态发生变化时,Observer对象将通过一个callback函数得到通知
  • ConcreteObserver
    • 观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理

设计模式_第4张图片

package com.Test.DesignPattern;

import java.util.Observable;

@SuppressWarnings("deprecation")
public class Person extends Observable {
    private String name;
    private String sex;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.setChanged();
        this.notifyObservers(name);
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.setChanged();
        this.notifyObservers(sex);
        this.sex = sex;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

Person类,具有name,age,sex三个属性。在Observe中监听这三个属性的变换

package com.Test.DesignPattern;

import java.util.Observable;
import java.util.Observer;

@SuppressWarnings("deprecation")
public class MyObserver implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        // TODO Auto-generated method stub
        System.out.println("对象改变" + (String)arg);
    }

}

自定义的监听类,每次监听对象改变的时候就会输出“对象改变”

package com.Test.DesignPattern;


public class Main {

    @SuppressWarnings("deprecation")
    public static void main(String[] args) {
        Person person = new Person();
        MyObserver observer1 = new MyObserver();
        MyObserver observer2 = new MyObserver();
        person.addObserver(observer1);//添加观察者
        person.addObserver(observer2);
        person.setName("test");
        person.setSex("nv");
        person.setAge(18);
        person.deleteObserver(observer1);// 删除观察者
    }
}

需要通过addObserver来注册观察者

  • Observe模式的典型应用
    • 监听时间驱动程序设计中的外部事件
    • 监听/监视某个对象的状态变化
    • 发布者/订阅者(publisher/subscriber)模型中,当一个外部事件(新的产品,消息的出现等等)被触发器时,通知邮件列表中的订阅者

你可能感兴趣的:(javaweb)