Design Mode
一、UML类图
1.简述
类图中类一般有三部分,类名、属性和类的操作
属性的表示方法:
可见性 名称:类型 [ = 默认值 ]
可见性:
+
公有public
#
受保护的protected
-
私有的private
默认值是可选项,表示属性的初值
类的操作表示方式:
可见性 名称([参数列表])[:返回列表]
eg.
2.类之间的关系
1.关联关系
通常将一个类的对象作为另一个类的属性
1)双向关联
默认情况下,关联是双向的,用直线连接
2)单向关联
用带箭头的直线连接
3)自关联
存在类的属性类型为该类本身
4)多重性关联
又称为重数性关联,表示一个类的对象与另一个类的对象连接的个数,在关联直线上添加数字表示对应另一
个类的对象的个数。
表示方式 | 解释 |
---|---|
1…1 | 表示该类只有1个对象与另一个类的1个对象进行关联 |
0…* | 表示该类没有或有多个对象与另一个类的1个对象进行关联 |
1…* | 表示该类有1个或多个对象与另一个类的1个对象进行关联 |
0…1 | 表示该类没有或有多个对象与另一个类的1个对象进行关联 |
m…n | 表示该类有最少m个最多n个对象与另一个类的1个对象进行关联 |
总结:
在一端点标注的数字表示该端点可以有多少个对象与另一端点的1个对象进行关联
每一个Button只属于一个Form,但是一个Form可以有零的或多个Button
5)聚合
表示整体和部分的关系,用带空心的菱形直线表示,但是部分可以脱离整体独立存在。
发动机时汽车的一部分,但是发动机可以独立存在
6)组合
表示整体和部分的关系,用带实心的菱形直线表示,但是部分与整体同生共死,整体不存在,部分也会消亡。
嘴巴是头的一部分,但是头没了嘴巴也就没了
2.依赖关系
通常在本类的方法中使用另一个类的对象作为参数,用带箭头的虚线表示
3.泛化关系
就是继承关系,也称为is-a-kind-of
,描述父类与子类之间的关系,父类又称为基类或超类,子类又称
为派生类,用带空心三角形的直线表示
4.实现关系
接口与类之间的实现关系,用带空心三角形的虚线表示
二、七大面向对象设计原则
可维护性:编程规范化,便于阅读理解
可重用性:相同功能的代码不用多次编写
可扩展性:增加新的功能时,非常方便
可靠性:增加新的功能对原有的功能没有影响
每一种设计模式都是按照七大设计原则来设计的,使用这些原则可以提高软件的可维护性、可重用性、可扩
展性和可靠性,使程序呈现高内聚、低耦合
1.单一职责原则
类的职责主要包括:数据职责(属性)和行为职责(方法)
一个类应该只包含单一的职责
一个类承担的职责越多,它被复用的可能性就越小,并且这些职责耦合在一起,当其中的一个职责发生变化
时,可能会影响其他职责的运行,这时就需要将这些职责进行分离,封装到不同的类中。
2.开闭原则
一个软件实体应该对扩展开放
,对修改关闭
因为XML、properties等格式的配置文件是纯文本文件,可以直接进行编辑不算对源码的修改,通过配置
文件、DOM解析和反射机制将具体类名存储在配置文件中,在运行时生成其实例对象。
3.里氏代换原则
所有引用父类的地方必须可以透明的使用其子类的对象
,程序将不会产生任何错误和异常
4.依赖倒转原则
抽象不应该依赖于细节,细节应该依赖于抽象
要针对接口编程,不要针对实现编程
5.接口隔离原则
如果一个接口太大,则需要将它分割成一些更细小的接口
,使用该接口的客户端只需要知道与之相关的方法
6.合成复用原则
在复用功能时多用关联关系,少用继承关系
7.迪米特法则
又称为最少知识原则,即一个对象应该对其他对象保持最小的了解
,降低系统的耦合度,使类与类直接保持松散
只与直接朋友通信,陌生类不要以局部变量形式出现在类的内部
直接朋友包括:
- 当前对象的成员变量
- 以参数形式传入当前对象方法中的对象
- 当前对象方法的返回值
三、设计模式
设计模式是设计与开发基于面向对象的软件的指导方针和成熟的解决方案,使用设计模式可以提高代码的可
重用性、可读性和可靠性
分类:
种类 | 作用 | 模式 |
---|---|---|
创建型模式(5种) | 主要用于创建对象 | 工厂方法模式 抽象工厂模式 建造者模式 原型模式 单例模式 |
结构型模式(7种) | 主要用于处理类或对象的组合 | 适配器模式 桥接模式 组合模式 装饰模式 外观模式 享元模式 代理模式 |
行为型模式(11种) | 主要用于描述对类或对象怎么交互和分配职责 | 职责链模式 命令模式 解释器模式 迭代器模式 中介者模式 备忘录模式 观察者模式 状态模式 策略模式 模版方法模式 访问者模式 |
*1.单例模式
1)饿汉式
/**
* 饿汉式(静态常量方式)
*/
public class HungrySingleton1 {
//静态常量 类加载时创建单例对象
private final static HungrySingleton1 singleton = new HungrySingleton1();
/**
* 构造器私有化
*/
private HungrySingleton1(){
}
/**
* 使用静态方法返回单例对象
* @return singleton
*/
public static HungrySingleton1 getInstance(){
return singleton;
}
}
/**
* 饿汉式(静态代码块方式)
*/
public class HungrySingleton2 {
private static HungrySingleton2 singleton;
//静态代码块 创建单例对象
static {
singleton = new HungrySingleton2();
}
/**
* 构造器私有化
*/
private HungrySingleton2(){
}
/**
* 使用静态方法返回单例对象
* @return singleton
*/
public static HungrySingleton2 getInstance(){
return singleton;
}
}
@Test
public void testHungrySingleton1(){
HungrySingleton1 singleton1 = HungrySingleton1.getInstance();
HungrySingleton1 singleton2 = HungrySingleton1.getInstance();
System.out.println(singleton1 == singleton2); //true
System.out.println(singleton1.hashCode()); //1349277854
System.out.println(singleton2.hashCode()); //1349277854
}
@Test
public void testHungrySingleton2(){
HungrySingleton2 singleton1 = HungrySingleton2.getInstance();
HungrySingleton2 singleton2 = HungrySingleton2.getInstance();
System.out.println(singleton1 == singleton2); //true
System.out.println(singleton1.hashCode()); //1349277854
System.out.println(singleton2.hashCode()); //1349277854
}
总结:
代码简单,是线程安全的
但是在类加载时会自动创建单例对象,可能没有被使用,浪费空间,没有进行懒加载
2)懒汉式
/**
* 懒汉式(线程不安全)
*/
public class LazySingleton1 {
private static LazySingleton1 singleton;
private LazySingleton1() {
}
public static LazySingleton1 getInstance(){
if(singleton == null)
{
singleton = new LazySingleton1();
}
return singleton;
}
}
@Test
public void testLazySingleton1() {
LazySingleton1 singleton1 = LazySingleton1.getInstance();
LazySingleton1 singleton2 = LazySingleton1.getInstance();
System.out.println(singleton1 == singleton2); //true
System.out.println(singleton1.hashCode()); //1349277854
System.out.println(singleton2.hashCode()); //1349277854
}
@Test
public void testLazySingleton1Thread() {
Runnable runnable = () -> {
String threadName = Thread.currentThread().getName();
LazySingleton1 s1 = LazySingleton1.getInstance();
System.out.println("线程 " + threadName + "\t => " + s1.hashCode());
};
for (int i = 0; i < 100; i++) {
new Thread(runnable, "" + i).start();
}
}
/**
* 懒汉式(线程安全,方法上添加synchronized关键字,效率低)
*/
public class LazySingleton2 {
private static LazySingleton2 singleton;
private LazySingleton2() {
}
public static synchronized LazySingleton2 getInstance(){
if(singleton == null)
{
singleton = new LazySingleton2();
}
return singleton;
}
}
@Test
public void testLazySingleton2() {
LazySingleton2 singleton1 = LazySingleton2.getInstance();
LazySingleton2 singleton2 = LazySingleton2.getInstance();
System.out.println(singleton1 == singleton2); //true
System.out.println(singleton1.hashCode()); //1349277854
System.out.println(singleton2.hashCode()); //1349277854
}
@Test
public void testLazySingleton2Thread() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1000);
Runnable runnable = () -> {
String threadName = Thread.currentThread().getName();
LazySingleton2 s1 = LazySingleton2.getInstance();
System.out.println("线程 " + threadName + "\t => " + s1.hashCode());
countDownLatch.countDown();
};
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
new Thread(runnable, "" + i).start();
}
countDownLatch.await();
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - start));
}
/**
* 懒汉式(线程安全,DCL双重检测锁机制,效率较高推荐使用)
*/
public class LazySingleton3 {
private static volatile LazySingleton3 singleton;
private LazySingleton3(){
}
public static LazySingleton3 getInstance()
{
if(singleton == null)
{
synchronized (LazySingleton3.class)
{
if(singleton == null)
{
singleton = new LazySingleton3();
}
}
}
return singleton;
}
}
@Test
public void testLazySingleton3() {
LazySingleton3 singleton1 = LazySingleton3.getInstance();
LazySingleton3 singleton2 = LazySingleton3.getInstance();
System.out.println(singleton1 == singleton2); //true
System.out.println(singleton1.hashCode()); //1349277854
System.out.println(singleton2.hashCode()); //1349277854
}
@Test
public void testLazySingleton3Thread() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1000);
Runnable runnable = () -> {
String threadName = Thread.currentThread().getName();
LazySingleton3 s1 = LazySingleton3.getInstance();
System.out.println("线程 " + threadName + "\t => " + s1.hashCode());
countDownLatch.countDown();
};
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
new Thread(runnable, "" + i).start();
}
countDownLatch.await();
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - start));
}
3)静态内部类
/**
* 静态内部类实现单例模式,是线程安全的
*/
public class InnerClassSingleton {
private static InnerClassSingleton singleton;
private InnerClassSingleton(){
}
/**
* 外部类InnerClassSingleton加载时 不会立即加载静态内部类Singleton
*/
public static class Singleton {
private final static InnerClassSingleton INSTANCE = new InnerClassSingleton();
}
/**
* 调用静态方法getInstance 加载静态内部类Singleton
* @return
*/
public static InnerClassSingleton getInstance(){
return Singleton.INSTANCE;
}
}
@Test
public void testInnerClassSingleton() {
InnerClassSingleton.Singleton singleton1 = InnerClassSingleton.getInstance();
InnerClassSingleton.Singleton singleton2 = InnerClassSingleton.getInstance();
System.out.println(singleton1 == singleton2); //true
System.out.println(singleton1.hashCode()); //1349277854
System.out.println(singleton2.hashCode()); //1349277854
}
@Test
public void testInnerClassSingletonThread() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1000);
Runnable runnable = () -> {
String threadName = Thread.currentThread().getName();
InnerClassSingleton s1 = InnerClassSingleton.getInstance();
System.out.println("线程 " + threadName + "\t => " + s1.hashCode());
countDownLatch.countDown();
};
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
new Thread(runnable, "" + i).start();
}
countDownLatch.await();
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - start));
}
4)枚举
/**
* 枚举实现单例模式, 可以防止反射爆破
*/
public enum EnumSingleton{
INSTANCE;
public static EnumSingleton getInstance(){
return INSTANCE;
}
}
@Test
public void testEnumSingleton() {
EnumSingleton singleton1 = EnumSingleton.INSTANCE;
EnumSingleton singleton2 = EnumSingleton.INSTANCE;
System.out.println(singleton1 == singleton2); //true
System.out.println(singleton1.hashCode()); //1349277854
System.out.println(singleton2.hashCode()); //1349277854
}
@Test
public void testEnumSingletonThread() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1000);
Runnable runnable = () -> {
String threadName = Thread.currentThread().getName();
EnumSingleton s1 = EnumSingleton.INSTANCE;
System.out.println("线程 " + threadName + "\t => " + s1.hashCode());
countDownLatch.countDown();
};
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
new Thread(runnable, "" + i).start();
}
countDownLatch.await();
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - start));
}
反射爆破:
使用jad
工具,将EnumSingleton.class转换成EnumSingle.java文件
@Test
public void testEnumSingletonReflection() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
EnumSingleton singleton1 = EnumSingleton.getInstance();
Class<EnumSingleton> aClass = EnumSingleton.class;
Constructor<EnumSingleton> constructor = aClass.getDeclaredConstructor(String.class, int.class);
//反射爆破
constructor.setAccessible(true);
EnumSingleton singleton2 = constructor.newInstance();
System.out.println(singleton1 == singleton2);
}
2.简单工厂模式
根据工厂方法所传入的参数来动态决定创建哪一个类的实例,不属于23种设计模式之一
结构图:
Factory:工厂类,负责创建所有实例,类中提供静态工厂方法,返回一个抽象产品类Product
Product:抽象产品,是所有产品的父类,类中有所有实例共有的接口
ConcreteProduct:工厂模式真正创建的具体产品
支付平台(包括现金支付、信用卡支付、支付宝支付和微信支付):
结构图:
public interface Pay {
/**
* 支付接口
*/
void pay();
}
public class CashPay implements Pay{
/**
* 实现现金支付
*/
@Override
public void pay() {
System.out.println("用户使用现金支付...");
}
}
public class CreditCardPay implements Pay{
/**
* 实现信用卡支付
*/
@Override
public void pay() {
System.out.println("用户使用信用卡支付...");
}
}
public class AliPay implements Pay{
/**
* 实现支付宝支付
*/
@Override
public void pay() {
System.out.println("用户使用支付宝支付...");
}
}
public class WeXinPay implements Pay{
/**
* 实现微信支付
*/
@Override
public void pay() {
System.out.println("用户使用微信支付...");
}
}
//支付工厂
public class PayFactory {
public static Pay distinguish() {
Pay p = null;
String payMethod = XMLUtil.getStr("src/com/qingsongxyz/factory/simplefactory/configPay.xml", "payMethod");
if (payMethod.equalsIgnoreCase("cash"))
{
p = new CashPay();
}
else if(payMethod.equalsIgnoreCase("CreditCard"))
{
p = new CreditCardPay();
}
else if(payMethod.equalsIgnoreCase("WeXin"))
{
p = new WeXinPay();
}
else if(payMethod.equalsIgnoreCase("ali"))
{
p = new AliPay();
}
else
{
throw new RuntimeException("本支付平台暂不支持" + payMethod + "支付!!!");
}
return p;
}
}
/**
* XML工具类,读取XMl中的标签内容
*/
public class XMLUtil {
public static String getStr(String fileName,String tagName){
try {
DocumentBuilderFactory instance = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = instance.newDocumentBuilder();
Document document = builder.parse(new File(fileName));
NodeList list = document.getElementsByTagName(tagName);
Node node = list.item(0).getFirstChild();
return node.getNodeValue().trim();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<payMethod>CreditCard</payMethod>
</config>
public class Client {
public static void main(String[] args) {
Pay p = PayFactory.distinguish();
p.pay(); //用户使用信用卡支付...
}
}
简单工厂模式提供工厂类,将对象的创建和对象的本身业务处理进行分离,降低系统的耦合度
但扩展困难,违背开闭原则,增加一个产品需要添加具体产品类并修改工厂类的逻辑
*3.工厂方法模式
在简单工厂的基础上添加抽象工厂,负责定义创建产品对象的公共接口,而具体工厂负责生成具体的产品
结构图:
Product:抽象产品,定义产品的接口,是所有产品的父类
ConcreteProduct:具体产品
Factory:抽象工厂,声明工厂方法,返回一个Product对象
ConcreteFactory:具体工厂,生产具体的产品
电视机生产工厂:
结构图:
/**
* 抽象产品类
*/
public interface TV {
void play();
}
public class HaierTV implements TV{
@Override
public void play() {
System.out.println("海尔电视机播放中...");
}
}
public class HisenseTV implements TV{
@Override
public void play() {
System.out.println("海信电视机播放中...");
}
}
/**
* 抽象工厂类
*/
public interface TVFactory {
TV produce();
}
public class HaierTVFactory implements TVFactory{
@Override
public TV produce() {
System.out.println("海尔电视机工厂生产海尔电视机...");
return new HaierTV();
}
}
public class HisenseTVFactory implements TVFactory{
@Override
public TV produce() {
System.out.println("海信电视机工厂生产海信电视机...");
return new HisenseTV();
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<TVFactory>com.qingsongxyz.factory.factorymethod.HisenseTVFactory</TVFactory>
</config>
public class Client {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
String className = XMLUtil.getStr("src/com/qingsongxyz/factory/factorymethod/configTV.xml", "TVFactory");
Class<?> aClass = Class.forName(className);
TVFactory tvFactory = (TVFactory) aClass.newInstance();
TV tv = tvFactory.produce();
tv.play();
}
}
/*
海信电视机工厂生产海信电视机...
海信电视机播放中...
*/
在增加新的产品时,不需要修改抽象工厂、其他具体工厂、具体产品和客户端,只需要添加新的具体工厂和
具体产品即可,扩展性更好,符合开闭原则
*4.抽象工厂模式
工厂方法模式时抽象工厂模式的一种特例,在工厂方法模式中每个具体的工厂只能生产一种具体的产品,而
在抽象工厂模式中一个具体的工厂可以生产多个具体的产品
相关概念:
1.产品等级结构:
即产品的继承结构,如抽象类时电视机,其子类有不同品牌的电视机
2.产品族
指同一工厂生产的,位于不同产品等级结构的一组产品,如海尔工厂生产海尔电视机、海尔冰箱和海尔空调
结构图:
AbstractFactory:抽象工厂,声明生成抽象产品的方法,每一个方法对应一个产品结构
ConcreteFactory:具体工厂,生成一组具体的产品,这些产品构成一个产品族,每个产品都位于某个产品
等级结构中
AbstractProduct:抽象产品,定义产品的抽象业务方法
ConcreteProduct:具体产品,实行具体产品业务
电器工厂:
结构图:
/**
* 抽象产品类
*/
public interface TV {
void work();
}
public class HaierTV implements TV {
@Override
public void work() {
System.out.println("海尔电视机工作中...");
}
}
public class HisenseTV implements TV {
@Override
public void work() {
System.out.println("海信电视机工作中...");
}
}
/**
* 抽象产品类
*/
public interface AirConditioner {
void work();
}
public class HaierAirConditioner implements AirConditioner{
@Override
public void work() {
System.out.println("海尔空调工作中...");
}
}
public class HisenseAirConditioner implements AirConditioner{
@Override
public void work() {
System.out.println("海信空调工作中...");
}
}
/**
* 抽象产品类
*/
public interface Fridge {
void work();
}
public class HaierFridge implements Fridge{
@Override
public void work() {
System.out.println("海尔冰箱工作中...");
}
}
public class HisenseFridge implements Fridge{
@Override
public void work() {
System.out.println("海信冰箱工作中...");
}
}
/**
* 抽象工厂
*/
public interface Factory {
TV produceTV();
AirConditioner produceAirConditioner();
Fridge produceFridge();
}
public class HaierFactory implements Factory {
@Override
public TV produceTV() {
System.out.println("海尔工厂生产海尔电视...");
return new HaierTV();
}
@Override
public AirConditioner produceAirConditioner() {
System.out.println("海尔工厂生产海尔空调...");
return new HaierAirConditioner();
}
@Override
public Fridge produceFridge() {
System.out.println("海尔工厂生产海尔冰箱...");
return new HaierFridge();
}
}
public class HisenseFactory implements Factory {
@Override
public TV produceTV() {
System.out.println("海信工厂生产海信电视...");
return new HisenseTV();
}
@Override
public AirConditioner produceAirConditioner() {
System.out.println("海信工厂生产海信空调...");
return new HisenseAirConditioner();
}
@Override
public Fridge produceFridge() {
System.out.println("海信工厂生产海信冰箱...");
return new HisenseFridge();
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<factory>com.qingsongxyz.factory.abstractfactory.HisenseFactory</factory>
</config>
public class Client {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
String className = XMLUtil.getStr("src/com/qingsongxyz/factory/abstractfactory/configFactory.xml", "factory");
Class<?> aClass = Class.forName(className);
Factory factory = (Factory) aClass.newInstance();
TV tv = factory.produceTV();
AirConditioner airConditioner = factory.produceAirConditioner();
Fridge fridge = factory.produceFridge();
tv.work();
airConditioner.work();
fridge.work();
}
}
/*
海信工厂生产海信电视...
海信工厂生产海信空调...
海信工厂生产海信冰箱...
海信电视机工作中...
海信空调工作中...
海信冰箱工作中...
*/
增加新的产品族和具体工厂很方便,不需要修改原有代码,符合开闭原则,但是增加新的产品等级结构需要
修改抽象工厂和所有具体工厂,不能很好的支持开闭原则
*5.建造者模式
用于创建一个包含多个组成部分的复杂对象,可以返回一个完整的产品对象返回
结构图:
Builder:抽象建造者,定义创建Product对象的各个部件的接口
ConcreteBuilder:具体构造者,实现各个部件的构造和装配方法
Product:产品,被构建的复杂对象,包括多个组件
Director:指挥者,负责安排复杂对象的建造次序
KFC套餐:
结构图:
/**
* 产品类
*/
public class Meal {
private String food;
private String drink;
public String getFood() {
return food;
}
public void setFood(String food) {
this.food = food;
}
public String getDrink() {
return drink;
}
public void setDrink(String drink) {
this.drink = drink;
}
}
/**
* 抽象建造者
*/
public abstract class MealBuilder {
protected Meal meal = new Meal();
public abstract void buildFood();
public abstract void buildDrink();
public Meal getResult(){
return meal;
}
}
public class SubMealBuilderA extends MealBuilder{
@Override
public void buildFood() {
meal.setFood("一个鸡腿堡");
}
@Override
public void buildDrink() {
meal.setDrink("一杯可乐");
}
}
public class SubMealBuilderB extends MealBuilder{
@Override
public void buildFood() {
meal.setFood("一个鸡肉卷");
}
@Override
public void buildDrink() {
meal.setDrink("一杯果汁");
}
}
/**
* 指挥者
*/
public class KFCWaiter {
private MealBuilder mealBuilder;
public void setMealBuilder(MealBuilder mealBuilder) {
this.mealBuilder = mealBuilder;
}
public Meal construct(){
mealBuilder.buildFood();
mealBuilder.buildDrink();
return mealBuilder.getResult();
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<builder>com.qingsongxyz.builder.SubMealBuilderA</builder>
</config>
public class Client {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
KFCWaiter waiter = new KFCWaiter();
String builder = XMLUtil.getStr("src/com/qingsongxyz/builder/configBuilder.xml", "builder");
Class<?> aClass = Class.forName(builder);
MealBuilder mealBuilder = (MealBuilder) aClass.newInstance();
waiter.setMealBuilder(mealBuilder);
Meal meal = waiter.construct();
System.out.println("套餐组成:");
System.out.println(meal.getFood());
System.out.println(meal.getDrink());
}
}
/*
套餐组成:
一个鸡腿堡
一杯可乐
*/
将产品本身与产品的创建过程解耦,增加新的具体建造者不需要修改原来的代码,符合开闭原则
*6.原型模式
通过克隆的方式复制出多个相同的对象
结构图:
Prototype:抽象原型类,定义克隆自己的方法
ConcretePrototype:具体原型类,实现具体的克隆方法
Client:客户类,让一个原型克隆自身从而创建一个新的对象
在Java中,想要实现克隆必须实现Cloneable接口,表示该类支持克隆
浅克隆:只复制对象中的所有基本数据类型成员,而引用类型成员还是指向原来的对象(Cloneable)
深克隆:不管是基本数据类型还是引用类型都复制(Serializable)
邮件复制(浅克隆):
public class Attachment {
public void download(){
System.out.println("下载附件...");
}
}
/**
* cloneable实现浅拷贝
*/
public class Email implements Cloneable{
private Attachment attachment;
public Email() {
attachment = new Attachment();
}
@Override
protected Object clone() {
Email clone = null;
try {
clone = (Email) super.clone();
} catch (CloneNotSupportedException e) {
System.out.println("克隆失败!!!");
}
return clone;
}
public Attachment getAttachment() {
return attachment;
}
public void display(){
System.out.println("查看邮件...");
}
}
public class Client {
public static void main(String[] args) {
Email email = new Email();
Email clone = (Email) email.clone();
System.out.println(email == clone); //false
System.out.println(email.getClass() == clone.getClass()); //true
System.out.println(email.getAttachment() == clone.getAttachment()); //true
}
}
邮件复制(深克隆):
结构图:
public class Attachment implements Serializable {
public void download(){
System.out.println("下载附件...");
}
}
/**
* 序列化实现深拷贝
*/
public class Email implements Serializable {
private Attachment attachment;
public Email() {
attachment = new Attachment();
}
public Object deepClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
}
public Attachment getAttachment() {
return attachment;
}
public void display(){
System.out.println("查看邮件...");
}
}
public class Client {
public static void main(String[] args) {
Email email = new Email();
Email clone = null;
try {
clone = (Email) email.deepClone();
System.out.println(email == clone); //false
System.out.println(email.getClass() == clone.getClass()); //true
System.out.println(email.getAttachment() == clone.getAttachment()); //false
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
在对已存在的类进行改造时,必需修改其源代码,违背了开闭原则,并且实现深克隆时需要编写较为复杂的
代码
*7.适配器模式
让由于接口不兼容而不能够交互的类一起工作
适配器模式包括类适配器和对象适配器
类适配器结构图:
Adapter类实现Target接口并继承Adaptee类
对象适配器结构图:
Adapter类继承Target类并关联Adaptee类(Java无法多继承)
Target:目标抽象类,可以是抽象类或接口,也可以是具体的类
Adapter:适配器类,是适配模式的核心
Adaptee:适配者,即被适配的角色
Client:客户类,调用目标抽象类中的业务方法
仿生机器人(类适配器):
结构图:
public interface Robot {
void cry();
void move();
}
public class Dog {
public void wang(){
System.out.println("小狗汪汪叫...");
}
public void run(){
System.out.println("小狗快快跑...");
}
}
//继承Dog类实现Robot接口
public class DogAdapter extends Dog implements Robot{
@Override
public void cry() {
System.out.print("机器人模仿:");
wang();
}
@Override
public void move() {
System.out.print("机器人模仿:");
run();
}
}
public class Client {
public static void main(String[] args) {
Robot robot = new DogAdapter();
robot.cry();
robot.move();
}
}
/*
机器人模仿:小狗汪汪叫...
机器人模仿:小狗快快跑...
*/
数据排序查找(对象适配器):
结构图:
public abstract class SortAndSearch {
/**
* 快速排序重载
* @param arr 数组
*/
public void sort(int[] arr){
sort(arr, 0, arr.length - 1);
}
/**
* 快速排序
* @param arr 数组
* @param startIndex 起始下标
* @param endIndex 结束下标
*/
public void sort(int[] arr, int startIndex, int endIndex) {
if (startIndex >= endIndex) {
return;
}
int left = startIndex;
int right = endIndex;
//选择第一个元素为基准
int pivot = arr[startIndex];
while (left < right) {
//从最后一个元素向左扫描,找到一个比基准小的值,将其移到左边
while (right > left && arr[right] >= pivot) {
right--;
}
arr[left] = arr[right];
//从第一个元素向右扫描,找到一个比基准大的值移到右边
while (left < right && arr[left] <= pivot) {
left++;
}
arr[right] = arr[left];
}
//完成一趟后将基准复位
arr[left] = pivot;
//使用分治法
//对基准值左边的元素进行递归排序
sort(arr, startIndex, left - 1);
//对基准值右边的元素进行递归排序。
sort(arr, right + 1, endIndex);
}
/**
* 二分查找
* @param arr 数组
* @param value 要查找的值
* @return 查找值的下标
*/
public abstract int search(int[] arr, int value);
}
public class BinarySearch {
/**
* 二分查找
* @param arr 数组
* @param value 查找的值 异常或未找到时返回-1
*/
public int search(int[] arr, int value) {
if (arr == null || arr.length == 0) {
System.out.println("传入的数组不能为空!!!");
return -1;
}
if (value < arr[0] || value > arr[arr.length - 1]) {
return -1;
}
int low = 0;
int high = arr.length - 1;
while (low <= high) {
int mid = (low + high) / 2;
int midValue = arr[mid];
if(value == midValue)
{
return mid;
}
else if(midValue > value)
{
high = mid - 1;
}
else if(midValue < value)
{
low = mid + 1;
}
}
return -1;
}
}
//继承SortAndSearch类
public class Adapter extends SortAndSearch {
//关联BinarySearch类
private BinarySearch binarySearch;
public Adapter() {
binarySearch = new BinarySearch();
}
@Override
public int search(int[] arr, int value)
{
return binarySearch.search(arr, value);
}
}
public class Client {
public static void main(String[] args) {
int[] arr = {9, 3, 6, 1, 7, 2, 4, 5, 8};
SortAndSearch sortAndSearch = new Adapter();
sortAndSearch.sort(arr);
System.out.println("快速排序后:");
System.out.println(Arrays.toString(arr));
int value1 = 1;
int index1 = sortAndSearch.search(arr, 1);
System.out.println(index1 == -1 ? "在数组中未找到元素" + value1 : "找到元素" + value1 + ",下标为:" + index1);
int value2 = 9;
int index2 = sortAndSearch.search(arr, 9);
System.out.println(index2 == -1 ? "在数组中未找到元素" + value2 : "找到元素" + value2 + ",下标为:" + index2);
int value3 = 20;
int index3 = sortAndSearch.search(arr, 20);
System.out.println(index3 == -1 ? "在数组中未找到元素" + value3 : "找到元素" + value3 + ",下标为:" + index3);
}
}
/*
快速排序后:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
找到元素1,下标为:0
找到元素9,下标为:8
在数组中未找到元素20
*/
将目标类和适配器类解耦,引入适配器类来重用现有的适配器类,无需修改源代码,符合开闭原则
*8.桥接模式
将抽象部分与它的实现部分分离,使它们都可以独立地变化
Abstraction:抽象类,它和Implementor之间具有关联关系
RefinedAbstraction:扩充抽象类,实现了Abstraction中定义的抽象业务方法
Implementor:实现类接口
ConcreteImplementor:具体实现类,实现Implementor接口
跨平台视频播放器:
结构图:
public interface VideoFile {
void decode(String platform, String fileName);
}
public class AVIFile implements VideoFile{
@Override
public void decode(String platform, String fileName) {
System.out.println(platform + "播放" + fileName + ".AVI文件...");
}
}
public class MPEGFile implements VideoFile{
@Override
public void decode(String platform, String fileName) {
System.out.println(platform + "播放" + fileName + ".MPEG文件...");
}
}
public class RMVBFile implements VideoFile{
@Override
public void decode(String platform, String fileName) {
System.out.println(platform + "播放" + fileName + ".RMVB文件...");
}
}
public class WMVFile implements VideoFile {
@Override
public void decode(String platform, String fileName) {
System.out.println(platform + "播放" + fileName + ".WMV文件...");
}
}
public abstract class CrossSystemVideoPlayer {
protected VideoFile videoFile;
public void setVideoFile(VideoFile videoFile) {
this.videoFile = videoFile;
}
public abstract void play(String fileName);
}
public class WindowsPlatform extends CrossSystemVideoPlayer{
@Override
public void play(String fileName) {
videoFile.decode("Windows平台", fileName);
}
}
public class LinuxPlatform extends CrossSystemVideoPlayer{
@Override
public void play(String fileName) {
videoFile.decode("Linux平台", fileName);
}
}
public class UnixPlatform extends CrossSystemVideoPlayer{
@Override
public void play(String fileName) {
videoFile.decode("Unix平台", fileName);
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<platform>com.qingsongxyz.bridge.WindowsPlatform</platform>
<fileType>com.qingsongxyz.bridge.MPEGFile</fileType>
<fileName>video1</fileName>
</config>
public class Client {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
String platform = XMLUtil.getStr("src/com/qingsongxyz/bridge/configPlayer.xml", "platform");
String fileType = XMLUtil.getStr("src/com/qingsongxyz/bridge/configPlayer.xml", "fileType");
String fileName = XMLUtil.getStr("src/com/qingsongxyz/bridge/configPlayer.xml", "fileName");
Class<?> platformClass = Class.forName(platform);
CrossSystemVideoPlayer player = (CrossSystemVideoPlayer) platformClass.newInstance();
Class<?> fileClass = Class.forName(fileType);
VideoFile videoFile = (VideoFile) fileClass.newInstance();
player.setVideoFile(videoFile);
player.play(fileName);
}
}
/*
Windows平台播放video1.MPEG文件...
*/
使用关联关系代替继承关系,分离抽象接口和它的实现部分,提高了可扩展性
*9.组合模式
组合多个对象形成树形结构以表示"部分——整体"的层次结构
组合模式分为透明组合模式和安全组合模式
透明组合模式结构图:
Component中声明了所有用于管理成员对象的方法,确保所有的构件类都有相同的接口,客户端可以相同对
待
安全组合模式结构图:
Component中没有声明任何管理成员对象的方法,而是在Composite类中声明这些用于管理的方法,确保叶
子对象的安全
Component:抽象构件,为叶子构建和容器构建对象声明接口,定义了访问及管理它的自购件的方法
Leaf:叶子构件,表示叶子节点对象
Composite:容器构件,表示容器节点对象,包括子节点(叶子节点或容器节点)
Client:客户类,通过抽象构件接口访问和控制组合构件中的对象
文件和文件夹:
/**
* 抽象构件
*/
public abstract class AbstractFile {
public abstract void add(AbstractFile element);
public abstract void remove(AbstractFile element);
public abstract void display();
}
/**
* 叶子构件
*/
public class TextFile extends AbstractFile{
private String fileName;
public TextFile(String fileName) {
this.fileName = fileName;
}
@Override
public void add(AbstractFile element) {
System.out.println("文本文件没有子节点,不能进行添加操作!!!");
}
@Override
public void remove(AbstractFile element) {
System.out.println("文本文件没有子节点,不能进行删除操作!!!");
}
@Override
public void display() {
System.out.print("这是一个名为" + fileName + "的文本文件...");
}
}
/**
* 叶子构件
*/
public class VideoFile extends AbstractFile{
private String fileName;
public VideoFile(String fileName) {
this.fileName = fileName;
}
@Override
public void add(AbstractFile element) {
System.out.println("视频文件没有子节点,不能进行添加操作!!!");
}
@Override
public void remove(AbstractFile element) {
System.out.println("视频文件没有子节点,不能进行删除操作!!!");
}
@Override
public void display() {
System.out.print("这是一个名为" + fileName + "的视频文件...");
}
}
/**
* 叶子构件
*/
public class ImageFile extends AbstractFile{
private String fileName;
public ImageFile(String fileName) {
this.fileName = fileName;
}
@Override
public void add(AbstractFile element) {
System.out.println("图片文件没有子节点,不能进行添加操作!!!");
}
@Override
public void remove(AbstractFile element) {
System.out.println("图片文件没有子节点,不能进行删除操作!!!");
}
@Override
public void display() {
System.out.print("这是一个名为" + fileName + "的图片文件...");
}
}
/**
* 容器构件
*/
import java.util.ArrayList;
public class Directory extends AbstractFile{
private String dirName;
private ArrayList<AbstractFile> list;
public Directory(String dirName) {
this.dirName = dirName;
list = new ArrayList<>();
}
@Override
public void add(AbstractFile element) {
list.add(element);
}
@Override
public void remove(AbstractFile element) {
list.remove(element);
}
@Override
public void display() {
System.out.println(dirName + ">>");
for (AbstractFile file : list) {
System.out.print("\t");
file.display();
System.out.println();
}
}
}
public class Client {
public static void main(String[] args) {
AbstractFile imageFile = new ImageFile("image.jpg");
AbstractFile videoFile = new VideoFile("video.mp4");
AbstractFile textFile = new TextFile("text.txt");
AbstractFile resource = new Directory("资源");
AbstractFile directory = new Directory("新建文件夹");
imageFile.add(videoFile);
resource.add(imageFile);
resource.add(videoFile);
resource.add(textFile);
resource.add(directory);
resource.display();
}
}
/*
图片文件没有子节点,不能进行添加操作!!!
资源>>
这是一个名为image.jpg的图片文件...
这是一个名为video.mp4的视频文件...
这是一个名为text.txt的文本文件...
新建文件夹>>
*/
定义分层次的复杂对象,表示对象的全部或部分层次,使得增加构件更容易,符合开闭原则
*10.装饰模式
动态地给一个对象增加一些额外的职责,比生成子类实现更灵活
结构图:
Component:抽象构件,声明了在具体构件中实现的业务方法,给对象动态增加职责方法
ConcreteComponent:具体构件,实现了抽象构件
Decorator:抽象装饰类,用于个具体构件增加职责,但是具体职责在其子类中实现
ConcreteDecorator:具体装饰类,是抽象装饰类的子类,负责添加新的职责
变性金刚:
结构图:
/**
* 抽象构件
*/
public interface Transform {
void move();
}
/**
* 具体构件
*/
public class Car implements Transform{
public Car() {
System.out.println("变形金刚是一辆车...");
}
@Override
public void move() {
System.out.println("在陆地上移动!");
}
}
/**
* 抽象装饰类
*/
public class Changer implements Transform{
private Transform transform;
public Changer(Transform transform) {
this.transform = transform;
}
@Override
public void move() {
transform.move();
}
}
/**
* 具体装饰类
*/
public class Robot extends Changer{
public Robot(Transform transform) {
super(transform);
System.out.println("变成机器人...");
}
public void say() {
System.out.println("说话!");
}
}
/**
* 具体装饰类
*/
public class Airplane extends Changer{
public Airplane(Transform transform) {
super(transform);
System.out.println("变成飞机...");
}
public void fly(){
System.out.println("在天空飞翔!");
}
}
public class Client {
public static void main(String[] args) {
Transform transform = new Car();
transform.move();
Robot robot = new Robot(transform);
robot.move();
robot.say();
System.out.println("--------------------------");
Airplane airplane = new Airplane(transform);
airplane.move();
airplane.fly();
}
}
/*
变形金刚是一辆车...
在陆地上移动!
变成机器人...
在陆地上移动!
说话!
--------------------------
变成飞机...
在陆地上移动!
在天空飞翔!
*/
具体构件和具体装饰类可以独立变化,原有代码无序改变,符合开闭原则
11.外观模式
为子系统中的一组接口提供一个统一的入口,更加容易使用
结构图:
Facade:外观角色,将所有从客户端发来的请求委派到相应的子系统去
SubSystem:子系统角色,处理由外观类传过来的请求
电源总开关:
结构图:
public class Light {
private String position;
public Light(String position) {
this.position = position;
}
public void on(){
System.out.println(position + "灯打开...");
}
public void off(){
System.out.println(position + "灯关闭...");
}
}
public class Fan {
public void on(){
System.out.println("风扇打开...");
}
public void off(){
System.out.println("风扇关闭...");
}
}
public class AirConditioner {
public void on(){
System.out.println("空调打开...");
}
public void off(){
System.out.println("空调关闭...");
}
}
public class TV {
public void on(){
System.out.println("电视机打开...");
}
public void off(){
System.out.println("电视机关闭...");
}
}
public class GeneralSwitchFacade {
private Light[] lights;
private Fan fan;
private AirConditioner ac;
private TV tv;
public GeneralSwitchFacade(Light[] lights, Fan fan, AirConditioner ac, TV tv) {
this.lights = lights;
this.fan = fan;
this.ac = ac;
this.tv = tv;
}
public void on(){
for (Light light : lights) {
light.on();
}
fan.on();
ac.on();
tv.on();
}
public void off(){
for (Light light : lights) {
light.off();
}
fan.off();
ac.off();
tv.off();
}
}
public class Client {
public static void main(String[] args) {
Light[] lights = new Light[4];
lights[0] = new Light("客厅");
lights[1] = new Light("卧室");
lights[2] = new Light("厨房");
lights[3] = new Light("厕所");
Fan fan = new Fan();
AirConditioner airConditioner = new AirConditioner();
TV tv = new TV();
GeneralSwitchFacade generalSwitchFacade = new GeneralSwitchFacade(lights, fan, airConditioner, tv);
generalSwitchFacade.on();
System.out.println("-------------------");
generalSwitchFacade.off();
}
}
/*
客厅灯打开...
卧室灯打开...
厨房灯打开...
厕所灯打开...
风扇打开...
空调打开...
电视机打开...
-------------------
客厅灯关闭...
卧室灯关闭...
厨房灯关闭...
厕所灯关闭...
风扇关闭...
空调关闭...
电视机关闭...
*/
对客户屏蔽子系统组件,使得子系统使用更方便,子系统和客户之间松耦合
12.享元模式
运用共享技术有效地均支持大量细粒度的对象的复用
结构图:
FlyWeight:抽象享元类,声明一个接口,通过它接受并作用于外部状态
ConcreteFlyWeight:具体享元类,实现了抽象享元类,存储内部状态
UnsharedConcreteFlyWeight:非共享具体享元类
FlyWeightFactory:享元工厂类,创建并管理享元对象
(内部状态:存储在享元对象内部并不会随环境改变的状态,可以共享
外部状态:随环境改变,不可以共享的状态)
共享网络设备:
结构图:
/**
* 外部状态类
*/
public class Port {
private String port;
public Port(String port) {
this.port = port;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
}
/**
* 抽象享元类
*/
public interface NetworkDevice {
String getType();
void use(Port port);
}
/**
* 具体享元类
*/
public class Switch implements NetworkDevice {
private String type;
public Switch(String type) {
this.type = type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String getType() {
return type;
}
@Override
public void use(Port port) {
System.out.println("连接到" + type + "型号交换机的" + port.getPort() + "端口...");
}
}
/**
* 具体享元类
*/
public class Hub implements NetworkDevice {
private String type;
public Hub(String type) {
this.type = type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String getType() {
return type;
}
@Override
public void use(Port port) {
System.out.println("连接到" + type + "型号集线器的" + port.getPort() + "端口...");
}
}
/**
* 享元工厂类
*/
public class DeviceFactory {
private ArrayList<NetworkDevice> devices;
private int totalTerminal = 0;
public DeviceFactory(ArrayList<NetworkDevice> devices) {
this.devices = devices;
}
public NetworkDevice getNetworkDevice(String type){
for (NetworkDevice device : devices) {
if(device.getType().equalsIgnoreCase(type))
{
totalTerminal++;
return device;
}
}
return null;
}
public int getTotalDevice(){
return devices.size();
}
public int getTotalTerminal(){
return totalTerminal;
}
}
public class Client {
public static void main(String[] args) {
String switchType = "Cisco-WS-C2950-24";
String hubType = "TP-LINK-HF8M";
ArrayList<NetworkDevice> devices = new ArrayList<>();
Switch sw = new Switch(switchType);
Hub hub = new Hub(hubType);
devices.add(sw);
devices.add(hub);
DeviceFactory factory = new DeviceFactory(devices);
NetworkDevice s = factory.getNetworkDevice(switchType);
NetworkDevice h = factory.getNetworkDevice(hubType);
s.use(new Port("8080"));
h.use(new Port("9090"));
System.out.println(factory.getTotalDevice());
System.out.println(factory.getTotalTerminal());
}
}
/*
连接到Cisco-WS-C2950-24型号交换机的8080端口...
连接到TP-LINK-HF8M型号集线器的9090端口...
2
2
*/
极大地减少内存中对象的数量,使得相同或相似的对象在内存中只保存一份,外部状态相对独立,且不会影
响内部状态,使得享元对象可以在不同的环境中共享
*13.代理模式
给某个对象提供代理,并由代理对象控制对原对象的引用
结构图:
Subject:抽象角色,声明代理主题角色和真实角色的共同接口
Proxy:代理角色,关联真实角色,调用真实角色的职责,同时在此之前之后添加额外的业务
RealSubject:真实角色,实现了抽象角色业务
日志记录代理(静态代理):
结构图:
/**
* 抽象角色
*/
public interface AbstractSubject {
void method();
}
/**
* 真实角色
*/
public class Business implements AbstractSubject{
@Override
public void method() {
System.out.println("执行method()方法...");
}
}
/**
* 代理角色
*/
public class LoggerProxy implements AbstractSubject{
private Business business;
private final DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
public LoggerProxy() {
business = new Business();
}
private void preMethod() {
System.out.println("method()方法被调用,调用时间为" + pattern.format(LocalDateTime.now()));
}
@Override
public void method() {
preMethod();
//真正业务
business.method();
postMethod();
}
private void postMethod() {
System.out.println("method()方法调用成功,调用时间为" + pattern.format(LocalDateTime.now()));
}
}
public class Client {
public static void main(String[] args) {
AbstractSubject proxy = new LoggerProxy();
proxy.method();
}
}
好处:
代理角色可以代理真实对象职责,并添加额外的业务,使得真实对象职责更加纯粹,实现业务的分工
缺点:
代理角色和真实角色实现同一个接口,当接口发生改变时,需要更改两遍代码,代理类能够完成真实角色的
所有职责(不能进行权限控制)
歌星和经纪人(动态代理):
结构图:
/**
* 抽象角色
*/
public interface StarDuty {
void sing();
void donate();
}
/**
* 真实角色
*/
public class Star implements StarDuty{
@Override
public void sing() {
System.out.println("歌星唱歌...");
}
@Override
public void donate() {
System.out.println("歌星募捐...");
}
}
/**
* 代理角色
*/
public class Agent {
public void prepare()
{
System.out.println("经纪人筹备...");
}
public void post(){
System.out.println("经纪人善后...");
}
}
public class MyInvocationHandler implements InvocationHandler {
//真实角色
private Star star;
//代理角色
private Agent agent;
public MyInvocationHandler(Star star, Agent agent) {
this.star = star;
this.agent = agent;
}
//返回代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(), star.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//经纪人业务
agent.prepare();
//反射执行真实角色的方法
Object invoke = method.invoke(star, args);
//经纪人业务
agent.post();
return invoke;
}
}
public class Client {
public static void main(String[] args) {
//创建真实角色歌星和代理角色经纪人
Star star = new Star();
Agent agent = new Agent();
//生成动态代理对象
MyInvocationHandler invocationHandler = new MyInvocationHandler(star, agent);
StarDuty proxy = (StarDuty) invocationHandler.getProxyInstance();
//执行歌星职责
proxy.donate();
System.out.println("------------------------");
proxy.sing();
}
}
/*
经纪人筹备...
歌星募捐...
经纪人善后...
------------------------
经纪人筹备...
歌星唱歌...
经纪人善后...
*/
真实角色单独实现一个接口,代理类直接编写相关业务方法,然后调用处理程序InvocationHandler接口,及
使用Proxy类中的newProxyInstance方法动态的创建代理类,通过该对象 调用实现接口的方法即可。
*14.责任链模式
让多个对象都有可能接受请求,将这些对象连接成一条链,并且沿着这条链传递请求,知道有对象处理它为
止
结构图:
Handle:抽象处理者,定义了抽象请求的处理方法
ConcreteHandle:具体处理者,实现了处理请求的方法,在处理前进行判断是否有相应的处理权限,如果有
则进行处理,如果没有则将请求转发给后继者
Client:客户类,提出请求
审批假条:
结构图:
/**
* 请假条类
*/
public class LeaveRequest {
private String leaveName;
private int leaveDays;
public LeaveRequest(String leaveName, int leaveDays) {
this.leaveName = leaveName;
this.leaveDays = leaveDays;
}
public String getLeaveName() {
return leaveName;
}
public void setLeaveName(String leaveName) {
this.leaveName = leaveName;
}
public int getLeaveDays() {
return leaveDays;
}
public void setLeaveDays(int leaveDays) {
this.leaveDays = leaveDays;
}
}
/**
* 抽象处理类
*/
public abstract class Leader {
protected String name;
protected Leader successor;
public Leader(String name) {
this.name = name;
}
public void setSuccessor(Leader successor) {
this.successor = successor;
}
public abstract void handleRequest(LeaveRequest request);
}
/**
* 具体处理类
*/
public class Director extends Leader{
public Director(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if (request.getLeaveDays() < 3)
{
System.out.println(request.getLeaveName() + "请假" + request.getLeaveDays() + "天由主任" + name + "审批...");
}
else
{
if(successor != null)
{
successor.handleRequest(request);
}
}
}
}
/**
* 具体处理类
*/
public class Manager extends Leader{
public Manager(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if (request.getLeaveDays() < 10)
{
System.out.println(request.getLeaveName() + "请假" + request.getLeaveDays() + "天由经理" + name + "审批...");
}
else
{
if(successor != null)
{
successor.handleRequest(request);
}
}
}
}
/**
* 具体处理类
*/
public class GeneralManager extends Leader{
public GeneralManager(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if (request.getLeaveDays() < 30)
{
System.out.println(request.getLeaveName() + "请假" + request.getLeaveDays() + "天由总经理" + name + "审批...");
}
else
{
System.out.println(request.getLeaveName() + "请假" + request.getLeaveDays() + "天,超过一个月不予通过...");
}
}
}
public class Client {
public static void main(String[] args) {
Leader director = new Director("张三");
Leader manager = new Manager("李四");
Leader generalManager = new GeneralManager("王五");
director.setSuccessor(manager);
manager.setSuccessor(generalManager);
LeaveRequest leaveRequest1 = new LeaveRequest("赵六", 2);
LeaveRequest leaveRequest2 = new LeaveRequest("李华", 8);
LeaveRequest leaveRequest3 = new LeaveRequest("王红", 28);
LeaveRequest leaveRequest4 = new LeaveRequest("陈军", 100);
director.handleRequest(leaveRequest1);
director.handleRequest(leaveRequest2);
director.handleRequest(leaveRequest3);
director.handleRequest(leaveRequest4);
}
}
/*
赵六请假2天由主任张三审批...
李华请假8天由经理李四审批...
王红请假28天由总经理王五审批...
陈军请假100天,超过一个月不予通过...
*/
降低耦合度,不需要知道是哪一个对象处理了请求,增加新的请求很方便,符合开闭原则,但是如果建链不
当,可能会造成死循环
*15.命令模式
将请求封装为一个对象,使我们可用不同的请求对客户进行操作,支持对请求排队、记录日志和撤销等操作
结构图:
Command:抽象命令类,声明执行请求的excute()方法
ConcreteCommand:具体命令类,实现excute()方法
Invoker:调用者,请求的发送者
Receiver:接收者,具体实现请求业务处理
Client:客户类
顺序图:
加法器:
/**
* 抽象命令类
*/
public abstract class AbstractCommand {
public abstract int execute(int value);
public abstract int undo();
}
/**
* 接收者
*/
public class Adder {
private int num = 0;
public int add(int value) {
num += value;
return num;
}
}
/**
* 具体命令类
*/
public class AddCommand extends AbstractCommand {
private Adder adder = new Adder();
private int value;
@Override
public int execute(int value) {
this.value = value;
return adder.add(value);
}
@Override
public int undo() {
return adder.add(-value);
}
}
/**
* 调用者
*/
public class Form {
private AbstractCommand command;
public void setCommand(AbstractCommand command) {
this.command = command;
}
public void compute(int value)
{
int result = command.execute(value);
System.out.println("计算结果为:" + result);
}
public void undo(){
int undo = command.undo();
System.out.println("执行撤销,计算结果为:" + undo);
}
}
public class Client {
public static void main(String[] args) {
AbstractCommand addCommand = new AddCommand();
Form form = new Form();
form.setCommand(addCommand);
form.compute(5);
form.compute(10);
form.compute(20);
form.undo();
}
}
/*
计算结果为:5
计算结果为:15
计算结果为:35
执行撤销,计算结果为:15
*/
将请求者与接收者解耦,新的命令可以很容易的加入到系统中,符合开闭原则
16.解释器模式
定义语言(规定格式和语法的代码)的文法,并建立一个解释器来解释该语言中的句子
结构图:
AbstractExpression:抽象表达式,声明了抽象的解释操作
TerminalExpression:终结符表达式,实现终结符相关的解释操作
NonterminalExpression:非终结符表达式,实现非终结符相关的解释操作
Context:环境类,存储需要解释的语句
(**终结符号:**语言中用到的基本元素,一般不能再被分解,eg.名词,动词,形容词,助词,等等基本语言单位
**非终结符:**是一个递归形式的定义,由终结符和至少一个非终结符号组成)
构造一个语言解释器,完成整数间的乘、除和求模运算
结构图:
/**
* 抽象表达式节点类
*/
public interface Node {
int interpret();
}
/**
* 终结符表达式节点类
*/
public class ValueNode implements Node{
private int value;
public ValueNode(int value) {
this.value = value;
}
@Override
public int interpret() {
return this.value;
}
}
/**
* 非终结符表达式节点类
*/
public abstract class SymbolNode implements Node{
//该非终结符左边节点
protected Node left;
//该非终结符右边节点
protected Node right;
public SymbolNode(Node left, Node right) {
this.left = left;
this.right = right;
}
}
/**
* 乘法节点类
*/
public class MulNode extends SymbolNode{
public MulNode(Node left, Node right) {
super(left, right);
}
/**
* @return 返回表达式的乘积
*/
@Override
public int interpret() {
return super.left.interpret() * super.right.interpret();
}
}
/**
* 除法节点类
*/
public class DivNode extends SymbolNode{
public DivNode(Node left, Node right) {
super(left, right);
}
/**
* @return 返回表达式的商
*/
@Override
public int interpret() {
return super.left.interpret() / super.right.interpret();
}
}
/**
* 求模节点类
*/
public class ModNode extends SymbolNode{
public ModNode(Node left, Node right) {
super(left, right);
}
/**
* @return 返回表达式的模
*/
@Override
public int interpret() {
return super.left.interpret() % super.right.interpret();
}
}
/**
* 计算器类
*/
public class Calculator {
private Node node;
public void build(String statement){
Node left, right;
Stack<Node> stack = new Stack<>();
String[] statementArr = statement.split(" ");
for (int i = 0; i < statementArr.length; i++) {
if(statementArr[i].equalsIgnoreCase("*"))
{
left = stack.pop();
int val = Integer.parseInt(statementArr[++i]);
right = new ValueNode(val);
stack.push(new MulNode(left, right));
}else if(statementArr[i].equalsIgnoreCase("/")){
left = stack.pop();
int val = Integer.parseInt(statementArr[++i]);
right = new ValueNode(val);
stack.push(new DivNode(left, right));
}else if(statementArr[i].equalsIgnoreCase("%")){
left = stack.pop();
int val = Integer.parseInt(statementArr[++i]);
right = new ValueNode(val);
stack.push(new ModNode(left, right));
}else {
stack.push(new ValueNode(Integer.parseInt(statementArr[i])));
}
}
this.node = stack.pop();
}
public int compute(){
return node.interpret();
}
}
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
String statement = "3 * 4 / 2 % 4";
Calculator calculator = new Calculator();
calculator.build(statement);
int result = calculator.compute();
System.out.println(statement + " = " + result);
}
}
//3 * 4 / 2 % 4 = 2
优点:易于扩展
缺点:对于复杂的语法难以维护,递归执行效率较低
*17.迭代器模式
提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,也称为游标
结构图:
Iterator:抽象迭代器,定义了访问和遍历元素的接口
ConcreteIterator:具体迭代器,实现抽象迭代器,完成对聚合对象的遍历
Aggregate:抽象聚合类,存储对象并定义创建相应迭代器的接口
ConcreteAggre:具体聚合类,实现创建相应迭代器的接口
遥控器频道集合遍历:
结构图:
/**
* 抽象聚合类
*/
public interface TV {
TVIterator createIterator();
}
/**
* 具体聚合类
*/
public class TCL_TV implements TV {
private Object[] obj = {"湖南卫视", "北京卫视", "上海卫视", "湖北卫视", "黑龙江卫视"};
public Object[] getObj() {
return obj;
}
@Override
public TVIterator createIterator() {
return new TCLIterator(this);
}
}
/**
* 具体聚合类
*/
public class SkyworthTV implements TV{
private Object[] obj = {"CCTV-1", "CCTV-2", "CCTV-3", "CCTV-4", "CCTV-5"};
public Object[] getObj() {
return obj;
}
@Override
public TVIterator createIterator() {
return new SkyworthIterator(this);
}
}
/**
* 抽象迭代器
*/
public interface TVIterator {
void setChannel(int i);
Object currentChannel();
void next();
void previous();
boolean isLast();
boolean isFirst();
}
/**
* 具体迭代器
*/
public class TCLIterator implements TVIterator {
private TCL_TV tv;
private int currentIndex = 0;
public TCLIterator(TCL_TV tv) {
this.tv = tv;
}
@Override
public void setChannel(int i) {
currentIndex = i;
}
@Override
public Object currentChannel() {
return tv.getObj()[currentIndex];
}
@Override
public void next() {
if(currentIndex < tv.getObj().length) {
currentIndex++;
}
}
@Override
public void previous() {
if(currentIndex > 0)
{
currentIndex--;
}
}
@Override
public boolean isLast() {
return currentIndex == tv.getObj().length;
}
@Override
public boolean isFirst() {
return currentIndex == 0;
}
}
/**
* 具体迭代器
*/
public class SkyworthIterator implements TVIterator{
private SkyworthTV tv;
private int currentIndex = 0;
public SkyworthIterator(SkyworthTV tv) {
this.tv = tv;
}
@Override
public void setChannel(int i) {
currentIndex = i;
}
@Override
public Object currentChannel() {
return tv.getObj()[currentIndex];
}
@Override
public void next() {
if(currentIndex < tv.getObj().length) {
currentIndex++;
}
}
@Override
public void previous() {
if(currentIndex > 0)
{
currentIndex--;
}
}
@Override
public boolean isLast() {
return currentIndex == tv.getObj().length;
}
@Override
public boolean isFirst() {
return currentIndex == 0;
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<tv>com.qingsongxyz.iterator.SkyworthTV</tv>
</config>
public class Client {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
String brand = XMLUtil.getStr("src/com/qingsongxyz/iterator/configTV.xml", "tv");
Class<?> aClass = Class.forName(brand);
TV tv = (TV) aClass.newInstance();
TVIterator iterator = tv.createIterator();
while(!iterator.isLast())
{
System.out.println(iterator.currentChannel());
iterator.next();
}
}
}
/*
CCTV-1
CCTV-2
CCTV-3
CCTV-4
CCTV-5
*/
简化了聚合类,在一个聚类上可以有多个遍历,增加新的聚合类和迭代器类都很方便,符合开闭原则
18.中介者模式
用一个中介对象封装一系列对象交互,使得各对象不需要显示相互引用,松耦合
结构图:
Mediator:抽象中介类,定义一个接口用于和各个同事之间的通信
ConcreteMediator:具体中介类,协调各个同事实现协作行为
Colleague:抽象通识类,定义各同事的公有方法
ConcreteColleague:具体同事类,通过中介类和其他同事通讯
虚拟聊天室,普通会员可以给其他会员发送文本,钻石会员既可以发送文本也可以发送图片,聊天室还能过滤
敏感字符
结构图:
/**
* 抽象中介者
*/
public abstract class AbstractChatroom {
public abstract void register(Member member);
public abstract void sendText(String from, String to, String text);
public abstract void sendImage(String from, String to, String image);
}
/**
* 具体中介者(聊天群)
*/
public class ChatGroup extends AbstractChatroom {
private Hashtable<String, Member> members = new Hashtable<>();
/**
* 注册会员
*
* @param member 会员
*/
@Override
public void register(Member member) {
if (!members.contains(member)) {
members.put(member.getName(), member);
member.setChatroom(this);
}
}
/**
* 发送文本
* @param from 发送者
* @param to 接收者
* @param text 文本
*/
@Override
public void sendText(String from, String to, String text) {
Member member = members.get(to);
//过滤名敏感字符
text = text.replace("日", "*");
member.receiveText(from, text);
}
/**
* 发送图片
* @param from 发送者
* @param to 接收者
* @param image 图片
*/
@Override
public void sendImage(String from, String to, String image) {
Member member = members.get(to);
if (image.length() > 5) {
System.out.println("图片太大,发送失败!!!");
} else {
member.receiveImage(from, image);
}
}
}
/**
* 抽象同事类
*/
public abstract class Member {
protected AbstractChatroom chatroom;
protected String name;
public Member(String name) {
this.name = name;
}
public abstract void sendText(String to, String message);
public abstract void sendImage(String to, String image);
public void receiveText(String from, String message){
System.out.println(from + "发送文本给" + this.name + ",内容为:" + message);
}
public void receiveImage(String from, String image){
System.out.println(from + "发送图片给" + this.name + ",内容为:" + image);
}
public AbstractChatroom getChatroom() {
return chatroom;
}
public void setChatroom(AbstractChatroom chatroom) {
this.chatroom = chatroom;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 具体同事类(普通会员)
*/
public class CommonMember extends Member{
public CommonMember(String name) {
super(name);
}
@Override
public void sendText(String to, String message) {
System.out.println("普通会员发送信息:");
chatroom.sendText(this.name, to, message);
}
@Override
public void sendImage(String to, String image) {
System.out.println("普通会员不能发送图片!!!");
}
}
/**
* 具体同事类(钻石会员)
*/
public class DiamondMember extends Member{
public DiamondMember(String name) {
super(name);
}
@Override
public void sendText(String to, String message) {
System.out.println("钻石会员发送信息:");
chatroom.sendText(this.name, to, message);
}
@Override
public void sendImage(String to, String image) {
System.out.println("钻石会员发送图片:");
chatroom.sendImage(this.name, to, image);
}
}
public class Client {
public static void main(String[] args) {
AbstractChatroom chatGroup = new ChatGroup();
Member member1 = new DiamondMember("张三");
Member member2 = new DiamondMember("李四");
Member member3 = new CommonMember("王五");
Member member4 = new CommonMember("小芳");
Member member5 = new CommonMember("小红");
chatGroup.register(member1);
chatGroup.register(member2);
chatGroup.register(member3);
chatGroup.register(member4);
chatGroup.register(member5);
member1.sendText("李四", "李四,你好!");
member2.sendText("张三", "张三,你好!");
member1.sendText("李四", "今天天气不错,有日!");
member2.sendImage("张三", "一个很大很大的太阳");
member2.sendImage("张三", "太阳");
member3.sendImage("小芳", "还有问题吗?");
member3.sendText("小红", "还有问题吗?");
member4.sendText("小红", "还有问题吗?");
member5.sendText("小红", "还有问题吗?");
member5.sendImage("王五", "谢谢");
}
}
/*
钻石会员发送信息:
张三发送文本给李四,内容为:李四,你好!
钻石会员发送信息:
李四发送文本给张三,内容为:张三,你好!
钻石会员发送信息:
张三发送文本给李四,内容为:今天天气不错,有*!
钻石会员发送图片:
图片太大,发送失败!!!
钻石会员发送图片:
李四发送图片给张三,内容为:太阳
普通会员不能发送图片!!!
普通会员发送信息:
王五发送文本给小红,内容为:还有问题吗?
普通会员发送信息:
小芳发送文本给小红,内容为:还有问题吗?
普通会员发送信息:
小红发送文本给小红,内容为:还有问题吗?
普通会员不能发送图片!!!
*/
优点:简化对象之间的交互,将各个同事解耦
19.备忘录模式
保存一个对象的内部状态,用于撤销恢复
结构图:
Originator:原发器,用于创建备忘录并存储当前状态
Memento:备忘录,存储原发器的内部状态
Caretaker:负责人,负责保存备忘录,但不能修改
对于用户信息进行撤销
结构图:
/**
* 原发器(用户信息类)
*/
public class UserInfoDTO {
private String account;
private String password;
private String cellphone;
public Memento saveMemento(){
return new Memento(account, password, cellphone);
}
public void restoreMemento(Memento memento){
this.account = memento.getAccount();
this.password = memento.getPassword();
this.cellphone = memento.getCellphone();
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCellphone() {
return cellphone;
}
public void setCellphone(String cellphone) {
this.cellphone = cellphone;
}
@Override
public String toString() {
return "UserInfoDTO{" +
"account='" + account + '\'' +
", password='" + password + '\'' +
", cellphone='" + cellphone + '\'' +
'}';
}
}
/**
* 备忘录
*/
public class Memento {
private String account;
private String password;
private String cellphone;
public Memento(String account, String password, String cellphone) {
this.account = account;
this.password = password;
this.cellphone = cellphone;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCellphone() {
return cellphone;
}
public void setCellphone(String cellphone) {
this.cellphone = cellphone;
}
}
/**
* 负责人
*/
public class Caretaker {
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
public class Client {
public static void main(String[] args) {
UserInfoDTO userInfoDTO = new UserInfoDTO();
Caretaker caretaker = new Caretaker();
userInfoDTO.setAccount("张三");
userInfoDTO.setPassword("123456");
userInfoDTO.setCellphone("11000000000");
System.out.println("状态一:");
System.out.println(userInfoDTO);
caretaker.setMemento(userInfoDTO.saveMemento()); //保存备忘录
System.out.println("---------------------------");
userInfoDTO.setPassword("111111");
userInfoDTO.setCellphone("12312312321");
System.out.println("状态二:");
System.out.println(userInfoDTO);
System.out.println("---------------------------");
userInfoDTO.restoreMemento(caretaker.getMemento()); //从备忘录中恢复
System.out.println("回到状态一:");
System.out.println(userInfoDTO);
}
}
/*
状态一:
UserInfoDTO{account='张三', password='123456', cellphone='11000000000'}
---------------------------
状态二:
UserInfoDTO{account='张三', password='111111', cellphone='12312312321'}
---------------------------
回到状态一:
UserInfoDTO{account='张三', password='123456', cellphone='11000000000'}
*/
*20.观察者模式
定义一种一对多的依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都会得到通知并自动更新
结构图:
Subject:主题,被观察的对象,存储任意数量的观察者对象
ConcreteSubject:具体目标,包含经常改变的数据,当它的状态发生改变时,向它的各个观察者发出通知
Observer:抽象观察者,声明了更新数据的方法,对观察目标的改变做出反应
ConcreteObserver:具体观察者,存储有关状态
猫叫老鼠跑,狗也跟着叫:
结构图:
/**
* 抽象目标
*/
public abstract class Subject {
protected ArrayList<Observer> observers = new ArrayList<>();
public void attach(Observer observer){
observers.add(observer);
}
public void detach(Observer observer){
observers.remove(observer);
}
public abstract void cry();
}
/**
* 具体目标
*/
public class Cat extends Subject{
@Override
public void cry() {
System.out.println("猫叫...");
System.out.println("-----------");
for (Observer observer : observers) {
observer.response();
}
}
}
/**
* 抽象观察者
*/
public interface Observer {
void response();
}
/**
* 具体观察者
*/
public class Mouse implements Observer{
@Override
public void response() {
System.out.println("老鼠努力逃跑...");
}
}
/**
* 具体观察者
*/
public class Dog implements Observer{
@Override
public void response() {
System.out.println("狗跟着叫...");
}
}
public class Client {
public static void main(String[] args) {
Subject cat = new Cat();
Observer mouse = new Mouse();
Observer dog = new Dog();
cat.attach(mouse);
cat.attach(dog);
cat.cry();
}
}
/*
猫叫...
-----------
老鼠努力逃跑...
狗跟着叫...
*/
将表示层和逻辑层分离,定义了更新接口,增加新的观察者不需要修改源代码,符合开闭原则
21.状态模式
允许一个对象在其内部状态改变时改变行为,将对象状态从包含该状态的类中分离出来
结构图:
Context:环境类,它是拥有状态的对象,不同状态下行为不同
State:抽象状态类,定义特定状态相关行为
ConcreteState:具体状态类,具体状态类对应环境的一个具体状态
论坛系统系统用户分为新手、高手、专家对应不同的行为
结构图:
/**
* 环境类(论坛账户) 包括状态对象
* 经验值 状态
* 0 ~ 100 新手
* 100 ~ 1000 高手
* 1000+ 专家
*/
public class ForumAccount {
private AbstractState state;
private String name;
public ForumAccount(String name) {
this.name = name;
this.state = new PrimaryState(this);
System.out.println(this.name + "注册成功!");
System.out.println("----------------------------------------");
}
public void downloadFile(int score){
state.downloadFile(score);
}
public void writeNode(int score){
state.writeNote(score);
}
public void replyNote(int score){
state.replyNote(score);
}
public AbstractState getState() {
return state;
}
public void setState(AbstractState state) {
this.state = state;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 抽象状态类,定于业务方法基本实现
* 1.下载文件 扣除积分
* 2.发布留言 增加积分
* 3.恢复留言 增加积分
*
* 检查状态抽象函数
*/
public abstract class AbstractState {
protected ForumAccount account;
protected int point;
protected String stateName;
public abstract void checkState(int score);
public void downloadFile(int score){
System.out.println(account.getName() + "下载文件,扣除" + score + "积分...");
this.point -= score;
checkState(score);
System.out.println("剩余积分:" + this.point + "当前级别为:" + account.getState().stateName + "...");
}
public void writeNote(int score){
System.out.println(account.getName() + "发布留言,增加" + score + "积分...");
this.point += score;
checkState(score);
System.out.println("剩余积分:" + this.point + "当前级别为:" + account.getState().stateName + "...");
}
public void replyNote(int score){
System.out.println(account.getName() + "恢复留言,增加" + score + "积分...");
this.point += score;
checkState(score);
System.out.println("剩余积分:" + this.point + "当前级别为:" + account.getState().stateName + "...");
}
public int getPoint() {
return point;
}
public void setPoint(int point) {
this.point = point;
}
public String getStateName() {
return stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
}
/**
* 具体状态类(新手状态) 无法下载文件
*/
public class PrimaryState extends AbstractState {
public PrimaryState(AbstractState state) {
this.account = state.account;
this.point = state.getPoint();
this.stateName = "新手";
}
public PrimaryState(ForumAccount account) {
this.point = 0;
this.account = account;
this.stateName = "新手";
}
@Override
public void downloadFile(int score){
System.out.println("对不起" + account.getName() + ",你没有下载文件的权限!!!");
}
@Override
public void checkState(int score) {
if (point >= 1000) {
account.setState(new HighState(this));
} else if (point >= 100) {
account.setState(new MiddleState(this));
}
}
}
/**
* 具体状态类(高手状态) 发布留言 增加双倍积分
*/
public class MiddleState extends AbstractState {
public MiddleState(AbstractState state) {
this.account = state.account;
this.point = state.getPoint();
this.stateName = "高手";
}
@Override
public void writeNote(int score) {
System.out.println(account.getName() + "发布留言,增加" + score + " * 2个积分...");
this.point += score * 2;
checkState(score);
System.out.println("剩余积分:" + this.point + "当前级别为:" + account.getState().stateName + "...");
}
@Override
public void checkState(int score) {
if (point >= 1000) {
account.setState(new HighState(this));
} else if (point < 0) {
System.out.println("余额不足,文件下载失败!!!");
this.point += score;
} else if (point <= 100) {
account.setState(new PrimaryState(this));
}
}
}
/**
* 具体状态类(专家状态)
* 1.下载文件 扣减一半积分
* 2.发布留言 增加双倍积分
*/
public class HighState extends AbstractState {
public HighState(AbstractState state) {
this.account = state.account;
this.point = state.getPoint();
this.stateName = "专家";
}
@Override
public void downloadFile(int score) {
System.out.println(account.getName() + "下载文件,扣除" + score + " / 2个积分...");
this.point -= score / 2;
checkState(score);
System.out.println("剩余积分:" + this.point + "当前级别为:" + account.getState().stateName + "...");
}
@Override
public void writeNote(int score) {
System.out.println(account.getName() + "发布留言,增加" + score + " * 2个积分...");
this.point += score * 2;
checkState(score);
System.out.println("剩余积分:" + this.point + "当前级别为:" + account.getState().stateName + "...");
}
@Override
public void checkState(int score) {
if (point < 0) {
System.out.println("余额不足,文件下载失败!!!");
this.point += score;
} else if (point <= 100) {
account.setState(new PrimaryState(this));
} else if (point <= 1000) {
account.setState(new MiddleState(this));
}
}
}
public class Client {
public static void main(String[] args) {
ForumAccount account = new ForumAccount("张三");
account.writeNode(20);
System.out.println("-------------------------------------");
account.downloadFile(20);
System.out.println("-------------------------------------");
account.replyNote(100);
System.out.println("-------------------------------------");
account.writeNode(40);
System.out.println("-------------------------------------");
account.downloadFile(80);
System.out.println("-------------------------------------");
account.downloadFile(150);
System.out.println("-------------------------------------");
account.writeNode(1000);
System.out.println("-------------------------------------");
account.downloadFile(80);
System.out.println("-------------------------------------");
}
}
/*
张三注册成功!
----------------------------------------
张三发布留言,增加20积分...
剩余积分:20当前级别为:新手...
-------------------------------------
对不起,张三,你没有下载文件的权限!!!
-------------------------------------
张三恢复留言,增加100积分...
剩余积分:120当前级别为:高手...
-------------------------------------
张三发布留言,增加40* 2个积分...
剩余积分:200当前级别为:高手...
-------------------------------------
张三下载文件,扣除80积分...
剩余积分:120当前级别为:高手...
-------------------------------------
张三下载文件,扣除150积分...
余额不足,文件下载失败!!!
剩余积分:120当前级别为:高手...
-------------------------------------
张三发布留言,增加1000* 2个积分...
剩余积分:2120当前级别为:专家...
-------------------------------------
张三下载文件,扣除80 / 2个积分...
剩余积分:2080当前级别为:专家...
-------------------------------------
*/
*22.策略模式
定义一系列算法,将每一个算法封装起来,并让他们相互替换,也称为政策模式
结构图:
Context:环境类,使用算法
Strategy:抽象策略类,定义了执行算法的方法
ConcreteStrategy:具体策略类,实现具体的算法
旅游出行策略:
结构图:
/**
* 环境类
*/
public class Person {
private TravelStrategy strategy;
public void setStrategy(TravelStrategy strategy) {
this.strategy = strategy;
}
public void travel(){
strategy.travel();
}
}
/**
* 抽象策略类
*/
public interface TravelStrategy {
void travel();
}
/**
* 具体策略类
*/
public class AirplaneStrategy implements TravelStrategy{
@Override
public void travel() {
System.out.println("乘坐飞机旅游...");
}
}
/**
* 具体策略类
*/
public class TrainStrategy implements TravelStrategy{
@Override
public void travel() {
System.out.println("乘坐火车旅游...");
}
}
/**
* 具体策略类
*/
public class BicycleStrategy implements TravelStrategy{
@Override
public void travel() {
System.out.println("乘坐自行车旅游...");
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<strategy>com.qingsongxyz.strategy.AirplaneStrategy</strategy>
</config>
public class Client {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Person person = new Person();
String strategy = XMLUtil.getStr("src/com/qingsongxyz/strategy/configStrategy.xml", "strategy");
Class<?> aClass = Class.forName(strategy);
TravelStrategy travelStrategy = (TravelStrategy) aClass.newInstance();
person.setStrategy(travelStrategy);
person.travel();
}
}
/*
乘坐飞机旅游...
*/
可以选择算法和行为,灵活地增加新的算法或行为而不用修改原代码,符合开闭原则
*23.模版方法模式
定义一个操作中算法的骨架,而将具体实现交给子类实现
结构图:
AbstractClass:抽象类,定义一系列基本操作
ConcreteClass:具体子类,实现父类中的抽象方法
银行业务办理流程
结构图:
/**
* 抽象类(业务办理流程类)
*/
public abstract class BankTemplateMethod {
public void takeNumber(){
System.out.println("排队取号...");
}
public abstract void transact();
public void evaluate(){
System.out.println("反馈评分...");
}
public void process(){
this.takeNumber();
this.transact();
this.evaluate();
}
}
/**
* 具体子类(存款类)
*/
public class Deposit extends BankTemplateMethod{
@Override
public void transact() {
System.out.println("存款...");
}
}
/**
* 具体子类(取款类)
*/
public class Withdraw extends BankTemplateMethod{
@Override
public void transact() {
System.out.println("取款...");
}
}
/**
* 具体子类(转账类)
*/
public class Transfer extends BankTemplateMethod{
@Override
public void transact() {
System.out.println("转账...");
}
}
<?xml version="1.0"?>
<config>
<className>com.qingsongxyz.template.Withdraw</className>
</config>
public class Client {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
String className = XMLUtil.getStr("D:\\java project\\DesignMode\\src\\com\\qingsongxyz\\template\\config.xml", "className");
Class<?> aClass = Class.forName(className);
BankTemplateMethod method = (BankTemplateMethod) aClass.newInstance();
method.process();
System.out.println("-----------------------------------");
}
}
/*
排队取号...
取款...
反馈评分...
-----------------------------------
*/
24.访问者模式
对于系统中不同类型的对象,不同的访问者的访问方式不同,增加新的访问方式而不用改变原来的代码
结构图:
Visitor:抽象访问者,声明具体访问者的访问操作
ConcreteVisitor:具体访问者,实现抽象访问方法
Element:抽象元素,定义接受访问方法
ConcreteElement:具体元素,实现抽象方法
ObjectStructure:对象结构,存储元素
顾客在超时选择商品放入购物车,收银员计算价格
结构图:
/**
* 抽象访问者类
*/
public abstract class Visitor {
protected String name;
public void setName(String name) {
this.name = name;
}
public abstract void visit(Apple apple);
public abstract void visit(Book book);
}
/**
* 具体访问者(顾客)
*/
public class Customer extends Visitor{
@Override
public void visit(Apple apple) {
System.out.println("顾客" + name + "选苹果...");
}
@Override
public void visit(Book book) {
System.out.println("顾客" + name + "买书...");
}
}
/**
* 具体访问者(收银员)
*/
public class Saler extends Visitor {
@Override
public void visit(Apple apple) {
System.out.println("收银员" + name + "给苹果过秤,然后计算价格...");
}
@Override
public void visit(Book book) {
System.out.println("收银员" + name + "计算书的价格...");
}
}
/**
* 抽象元素(商品)
*/
public interface Product {
void accept(Visitor visitor);
}
/**
* 具体元素(苹果)
*/
public class Apple implements Product{
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
/**
* 具体元素(书)
*/
public class Book implements Product{
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
/**
* 对象结构(购物车)
*/
public class BuyBasket {
private ArrayList<Product> list = new ArrayList<>();
public void accept(Visitor visitor){
Iterator<Product> iterator = list.iterator();
while (iterator.hasNext())
{
iterator.next().accept(visitor);
}
}
public void addProduct(Product product){
list.add(product);
}
public void removeProduct(Product product){
list.remove(product);
}
}
<?xml version="1.0"?>
<config>
<className>com.qingsongxyz.visitor.Saler</className>
</config>
public class Client {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Product product1 = new Book();
Product product2 = new Book();
Product product3 = new Apple();
BuyBasket buyBasket = new BuyBasket();
buyBasket.addProduct(product1);
buyBasket.addProduct(product2);
buyBasket.addProduct(product3);
String className = XMLUtil.getStr("D:\\java project\\DesignMode\\src\\com\\qingsongxyz\\visitor\\config.xml", "className");
Class<?> aClass = Class.forName(className);
Visitor visitor = (Visitor) aClass.newInstance();
visitor.setName("张三");
buyBasket.accept(visitor);
}
}
/*
收银员张三计算书的价格...
收银员张三计算书的价格...
收银员张三给苹果过秤,然后计算价格...
*/