软件设计模式

七个设计原则

设计原则核心思想:
    1) 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
    2) 针对接口编程,而不是针对实现编程。
    3) 为了交互对象之间的松耦合设计而努力

单一职责原则

定义:
	就一个类而言,应该只有一个引起它变化的原因
理解:
	对于相同的功能,不要散落在各个类中(内聚性)
	一个类的职责单一(低耦合)

接口隔离原则

定义:
	客户端不应该依赖它不需要的接口
重构:
	把接口细分为更小的接口

依赖倒转原则

定义
	高层模块不应该依赖低层模块,二者都应该依赖其抽象
	抽象不应该依赖细节,细节应该依赖抽象
依赖体现:
	调用、继承、实现

里氏替换原则

定义:
	子类型必须能够替换父类型,且功能保持不变;尽量不重写,重载父类方法,来改变程序功能

开闭原则

定义:
	一个软件实体应该对扩展开放,对修改关闭
理解:
	满足客户新的需求扩展功能
	扩展同时不修改原有代码
实现关键:
	抽象(抽象类、接口)
实现方法:
	对于发生变化的功能进行抽象形成接口,给接口以不同实现
	模块间的调用通过接口进行

迪米特法则

定义:
	一个对象应该对其他对象保持最少的了解
	只与它的直接朋友通信
朋友:
	两个对象之间存在耦合关系称之为直接朋友,局部变量不是直接朋友

合成复用原则

定义:
	尽量少用继承,多用组合聚合实现复用

23种设计模式

创建型模式 : 单例模式 , 抽象工厂模式 , 原型模式 , 建造者模式 , 工厂模式

结构型模式 : 适配器模式 , 桥接模式 , 装饰模式 , 组合模式 , 外观模式 , 享元模式 , 代理模式

行为型模式 : 模板方法模式 , 命令模式 , 访问者模式 , 迭代器模式 , 观察者模式 , 中介者模式 , 备忘录模式 , 解释器模式 , 状态模式 , 策略模式 , 职责链模式

创建型设计模式

创建型模式 : 单例模式 , 抽象工厂模式 , 原型模式 , 建造者模式 , 工厂模式

单例模式

所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)

饿汉式(静态常量)应用实例 步骤如下:

  1. 构造器私有化 (防止 new )

  2. 类的内部创建对象

  3. 向外暴露一个静态的公共方法getInstance ();

  4. 代码实现

单例模式注意事项和细节说明

  • 单例模式保证了 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
  • 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new
  • 单例模式使用的场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session工厂等)
//但是可能造成内存浪费
//单例模式:饿汉式(静态常量)
public class StaticChangLiang {
    private final static StaticChangLiang instance = new StaticChangLiang();

    //提供私有的构造器,防止被new对象
    private StaticChangLiang() {
    }

    //提供静态公共方法,以便于其他类使用
    public static StaticChangLiang getInstance() {
        return instance;
    }
}
//单例模式:懒汉式(线程不安全),但是只能在单线程下使用.在多线程环境下不可使用这种方式 
public class UnSafe {
    private static UnSafe instance;

    private UnSafe() {
    }
    //只有在调用getInstance()方法时,才创建单例对象,饿汉式
    public static UnSafe getInstance() {
    //判断如果是空的说明第一次创建,就创建其实例赋值给成员变量
        if (instance == null) {
            instance = new UnSafe();
        }
        return instance;
    }
}//结论:在实际开发中,不要使用这种方式.
//懒汉式(线程安全)
public class Safe {
    private static Safe safe;

    private Safe() {
    }
    //加入同步代码,线程安全,同步方法,解决了线程不安全问题 
    public static synchronized Safe getInstance() {
        if (safe == null) {
            safe = new Safe();
        }
        return safe;
    }
}
 //效率太低了,每个线程在想获得类的实例时候,执行getInstance()方法都要进行同步。而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例, 直接return就行了。方法进行同步效率太低
//单例模式双重检查   线程安全;延迟加载;效率较高 
public class XianChengSafe {
    private static XianChengSafe xcs;

    public static synchronized XianChengSafe getInstance(){
        //ABCDE...多个线程
        if (xcs==null){
            synchronized (XianChengSafe.class){
                //A线程执行完并实例化后,B线程就会到这里,由于此时xcs已经不为空就直接跳过if
                if (xcs==null){
                    //A线程最先进入到这里
                    synchronized (XianChengSafe.class){
                        xcs = new XianChengSafe();
                    }
                }
            }
        }
        return xcs;
    }
}
/*
单例模式(静态内存类) 线程安全的,采用了类装载的机制来保证初始化实例时只有一个线程。
静态内部类方式在StaticSafe类被装载时并不会立即实例化,而是在需要实例化时,
调用getInstance方法,才会装载StaticSafeInstance类,从而完成StaticSafe的实例化
*/
public class StaticSafe {

    private StaticSafe(){

    }
    //提供一个私有的静态内部类
    private static class StaticSafeInstance{
        private final static StaticSafe instance = new StaticSafe();
    }

    public static StaticSafe getInstance(){
        return StaticSafeInstance.instance;
    }
}
//枚举:不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象
public enum Singleton {
    INSTANCE;
    public void method(){
        System.out.println("hello!");
    }
}
工厂模式

抽象工厂,在超类中通过自身的getFactory(String type)获得子类

fsf

一、有一个OEM制造商代理做HP笔记本(Laptop),后来该制造商得到了更多的品牌笔记本电脑的订单Acer,Lenovo,Dell,该OEM商发现,如果一次同时做很多个牌子的本本,有些不利于管理。利用工厂模式改善设计,用java控制台应用程序实现该OEM制造商的工厂模式。

UML类图
img

//工厂方法模式
public class FactoryMethod {
	public static void main(String[] args) {
		Computer c = null;
		Factory f = null;
		f = new DellFactory();
		c = f.getComputerType();
		c.ComputerType();
		f = new LenovoFactory();
		c = f.getComputerType();
		c.ComputerType();
		f = new AcerFactory();
		c = f.getComputerType();
		c.ComputerType();
	}
}
 
interface Factory{
	Computer getComputerType();
}
 
class DellFactory implements Factory{
	@Override
	public Computer getComputerType() {
		return new Dell();
	}
}
 
class AcerFactory implements Factory{
	@Override
	public Computer getComputerType() {
		return new Acer();
	}
}
 
class LenovoFactory implements Factory{
	@Override
	public Computer getComputerType() {
		return new Lenovo();
	}
}
 
interface Computer{
	public void ComputerType();
}
 
class Dell implements Computer{
	@Override
	public void ComputerType() {
		System.out.println("Dell Computer");	
	}
}
 
class Acer implements Computer{
 
	@Override
	public void ComputerType() {
		System.out.println("Acer Computer");	
	}
}

class Lenovo implements Computer{
	@Override
	public void ComputerType() {
		System.out.println("Lenovo Computer");	
	}
}

二、下图设计类图是关于游戏软件的设计

在这里插入图片描述

在该设计中,SlowGameFactory类负责创建SlowFighter对象与SlowMonster对象,并且将创建完的对象以其超类类型返回给ClientGUI对象。然后,ClientGUI对象将操纵SlowFighter对象与SlowMonster对象,使得它们互相打斗

1、上述设计使用了什么设计模式?
抽象工厂设计模式

2、请在以上设计类图中添加4个新的类MedFighter、SuperFighter、MedMonster和SuperMonster,以便使得MedFighter对象能够对应于MedMonster对象;SuperFighter对象能够对应于SuperMonster对象,绘制新设计类图;

3、除了以上添加的4个类以外,在以上类图中还应该添加什么类?
SuperGameFactory MedGameFactory

4、描述新的设计类图;
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类
一个抽象工厂类,可以派生出多个具体工厂类
每个具体工厂类可以创建多个具体产品类的实例,也就是创建的是一个产品线下的多个产品

5、明确说明新设计的优点。
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个

一个农场专门负责培育各种水果,有葡萄,草莓和苹果,类图如下,请按以下要求完 成水果生长状态的描述

在这里插入图片描述

1、使用简单工厂模式,绘制系统完整类图,完成对象的创建
在这里插入图片描述

2、编写工厂类和客户端主程序,并在主程序中完成草莓生长状态的描述

//SimpleFruitFactory.java
public class SimpleFruitFactory {
    public static Fruit getFruit(String type) {
        Fruit fruit = null;
        if (type.equals("Apple"))
            return new Apple();
        else if (type.equals("Grape"))
            return new Grape();
        else if (type.equals("Strawberry"))
            return new Strawberry();
        else
            return fruit;
    }
}
//Fruit.java
public interface Fruit {
    public void plant();
    public void grow();
    public void harvest();
}
//Apple.java
public class Apple implements Fruit{
    @Override
    public void plant() {
        System.out.println("apple is planting...");
    }
    @Override
    public void grow() {
        System.out.println("apple is growing...");
    }
    @Override
    public void harvest() {
        System.out.println("apple is harversting...");
    }
}
//Grape.java
public class Grape implements Fruit{
    @Override
    public void plant() {
        System.out.println("grape is planting...");
    }
    @Override
    public void grow() {
        System.out.println("grape is growing...");
    }
    @Override
    public void harvest() {
        System.out.println("grape is harversting...");
    }
}
//Strawberry.java
public class Strawberry implements Fruit{
    @Override
    public void plant() {
        System.out.println("strawberry is planting...");
    }
    @Override
    public void grow() {
        System.out.println("strawberry is planting...");
    }
    @Override
    public void harvest() {
        System.out.println("strawberry is planting...");
    }
}
//Client.java
public class Client {
    public static void main(String[] args) {
        Fruit f = SimpleFruitFactory.getFruit("Apple");
        f.plant();
        f.grow();
        f.harvest();
    }
}
建造者模式
  1. 建造者模式(Builder Pattern) 又叫生成器模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。

  2. 建造者模式 是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。

建造者模式的四个角色

  1. Product(产品角色): 一个具体的产品对象。
  2. Builder(抽象建造者): 创建一个Product对象的各个部件指定的 接口/抽象类。
  3. ConcreteBuilder(具体建造者): 实现接口,构建和装配各个部件。
  4. Director(指挥者): 构建一个使用Builder接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。

一般类图:超类可以是接口或者抽象类

在这里插入图片描述

下面为一个盖房子案例

需要建房子:这一过程为打桩、砌墙、封顶。不管是普通房子也好,高楼建筑也好都
需要经历这些过程,我们使用建造者模式完成

//产品类
public class House {
	private String baise;//地基
	private String wall;//墙
	private String roofed;//屋顶
	
	public String getBaise() {
		return baise;
	}
	public void setBaise(String baise) {
		this.baise = baise;
	}
	public String getWall() {
		return wall;
	}
	public void setWall(String wall) {
		this.wall = wall;
	}
	public String getRoofed() {
		return roofed;
	}
	public void setRoofed(String roofed) {
		this.roofed = roofed;
	}
}

//抽象的房屋建造者
public interface HouseBuilder {

	void builderBaise();
	void buildWalls();
	void buildRoofed();
	House buildHouse();
}

//具体的普通房屋建造者
public class CommonHouse implements HouseBuilder{

	private House house = new House();
	
	@Override
	public void builderBaise() {
		house.setBaise("普通房子的地基");
	}

	@Override
	public void buildWalls() {
		house.setWall("普通房子的砌墙");
	}

	@Override
	public void buildRoofed() {
		house.setRoofed("普通房子的盖屋顶");
	}

	@Override
	public House buildHouse() {
		return house;
	}
}

//具体的高楼建筑建造者
public class HighBuilding implements HouseBuilder{

	private House house = new House();
	
	@Override
	public void builderBaise() {
		house.setBaise("高楼建筑的地基");
	}

	@Override
	public void buildWalls() {
		house.setWall("高楼建筑的砌墙");
	}

	@Override
	public void buildRoofed() {
		house.setRoofed("高楼建筑的屋顶");
	}

	@Override
	public House buildHouse() {
		return house;
	}
}

//指挥者
public class HouseDirector {

	private HouseBuilder hb;
	
	public HouseDirector(HouseBuilder hb) {
		this.hb=hb;
	}
	
	//指挥者负责构建什么样的房子
	public House constructHouse() {
		hb.builderBaise();
		hb.buildWalls();
		hb.buildRoofed();
		return hb.buildHouse();
	}
}

//测试类
public class Client {
	public static void main(String[] args) {
		HouseDirector hbirector = new HouseDirector(new CommonHouse());
		House house = hbirector.constructHouse();
		System.out.println(house.getBaise());
		System.out.println(house.getWall());
		System.out.println(house.getRoofed());
	}
}

建造者模式的注意事项和细节

  1. 客户端(使用程序)不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象

  2. 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象

  3. 可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程

  4. 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合 “开闭原则”

  5. 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。

  6. 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,因此在这种情况下,要考虑是否选择建造者模式.

在例2.5的设计中,添加一个经济型房屋生成器类,命名为EconHouseBuilder。注意经济型房屋的面积比较小,卧室、卫生间和车库的数量较少,切不包含花园和游泳池。设计并且写出实现代码,具体要求参见光盘的相应作业部分

在这里插入图片描述

原型模式
  1. 原型模式(Prototype模式)是指:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象

  2. 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节

  3. 工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建,即 对象.clone()

在这里插入图片描述

Prototype:原型类,声明一个克隆自己的接口

ConcretePrototype:具体的原型类

克隆羊案例

Sheep.java

package com.ligong.prototype;

//需要实现Cloneable接口,重写clone方法,注意将方法的异常改为try catch
public class Sheep implements Cloneable {

	private String name;
	private String color;
	private Integer age;

	public Sheep(String name, String color, Integer age) {
		super();
		this.name = name;
		this.color = color;
		this.age = age;
	}

	//get,set方法省略

	@Override
	public String toString() {
		return "Sheep [name=" + name + ", color=" + color + ", age=" + age + "]";
	}

	@Override
	protected Object clone() {
		Sheep sheep = null;
		try {
			sheep = (Sheep) super.clone();
		} catch (Exception e) {
			System.out.println(e);
		}
		return sheep;
	}

}

Client.java

package com.ligong.prototype;

public class Client {

	public static void main(String[] args) throws CloneNotSupportedException {
		Sheep sheep = new Sheep("肖恩", "yellow", 19);
		Sheep cloneSheep = (Sheep)sheep.clone();//通过clone方法直接返回克隆好的实例
		System.out.println(sheep);
		System.out.println(cloneSheep);
	}
}

(1)浅拷贝:我们只拷贝对象中的基本数据类型(8种),对于数组、容器、引用对象等都不会拷贝

(2)深拷贝:不仅能拷贝基本数据类型,还能拷贝那些数组、容器、引用对象等

深拷贝:

  • 复制对象的所有基本数据类型的成员变量值

  • 为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象进行拷贝

  • 深拷贝实现方式1:重写clone方法来实现深拷贝

  • 深拷贝实现方式2:通过对象序列化实现深拷贝

结构型设计模式

结构型模式 : 适配器模式 , 桥接模式 , 装饰者模式 , 组合模式 , 外观模式 , 代理模式

适配器模式
  1. 适配器模式(Adapter Pattern)将某个类的接口转换成客户端期望的另一个接口表示,主的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper)

  2. 适配器模式属于结构型模式

  3. 主要分为三类:类适配器模式、对象适配器模式

类适配器

在这里插入图片描述

以充电头案例为例,插座的电压是220v的,而我们手机需要5v的电压,这时充电器就相当于一个适配器,将220v的电压转化成我们可以使用的5v电压

//被适配的类,透明的,用户看不见的,无法对其直接修改
public class Voltage220V {
	
	public int output220V() {
		return 220;
	}
}

//目标类,我们期望的类,将原来类中的功能保留,并添加新的功能
public interface Voltage5V {
	public int output220V();
	public int output5V();
}

//使用适配器类将原来的被适配类转换成可期望的类
public class VoltageAdapter extends Voltage220V implements Voltage5V{

	//新增了5v的接口,原来的220v也可以继续使用
	@Override
	public int output5V() {
		return 5;
	}
}


public class Client {
	public static void main(String[] args) {
		Voltage5V v5 = new VoltageAdapter();
		System.out.println("使用了" + v5.output220V() + "伏的充电接口");
		System.out.println("使用了" + v5.output5V() + "伏的充电接口");
	}
}
对象适配器

由于java是单继承,这就导致了类适配器的局限性,对象适配器使用合成复用原则替换原来的继承关系

在这里插入图片描述

//使用适配器类将原来的被适配类转换成可期望的类
public class VoltageAdapter2 implements Voltage5V{

	private Voltage220V v220;

        public VoltageAdapter2(Voltage220V v220) {
		this.v220 = v220;
	}
	//保留原来220v的方法
	@Override
	public int output220V() {
		return v220.output220V();
	}
	
	//实现我们期望使用的方法
	@Override
	public int output5V() {
		return 5;
	}
}

public class Client {
	public static void main(String[] args) {
		Voltage5V voltage2 = new VoltageAdapter2(new Voltage220V());
		System.out.println("使用了" + voltage2.output220V() + "伏的充电接口");
		System.out.println("使用了" + voltage2.output5V() + "伏的充电接口");
	}
}

在这里插入图片描述

桥接模式

桥接模式是指将抽象部分与它的实现部分分离,使它们可以独立地变化

在这里插入图片描述

Abstraction接口:定义抽象部分的接口,维持Implementor对象的一个参考

RefinedAbstraction类:是一个实类,继承或实现Abstraction

Implementor接口:Implementor接口的结构形式可以不和Abstraction界面严格对应;Implementor接口通常只提供比较原始的功能,Abstraction接口通常提供比较高级的功能

ConcreteImplementor类:是一个具体的实现类

在这里插入图片描述

组合模式

组合模式指将对象组合成树形结构,以表示“部分-整体”的层次结构。在树形结构问题中模糊了简单元素和复杂元素的概念,客户端程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦

安全形式的组合模式:在Compsite类中声明所有用来管理子类对象的方法,而不再接口中

透明形式的组合模式:在Component类中声明所有用来管理子类对象的方法

类图:

在这里插入图片描述

案例:

​ 文件系统中的文件有不同类型,不同类型的文件其浏览方式有所区别,如文本文件和图片文件,视频文件的浏览方式就不同。对文件夹的浏览实际上就是对其中包含文件的浏览,而客户端可以一致地对文件和文件夹进行操作,无需关心他们的区别。使用组合模式来模拟文件额浏览操作(display),画出设计类图

在这里插入图片描述

案例2:

​ 使用组合模式设计一个杀毒软件的框架,该软件既可以对某个文件夹杀毒,也可以对指定文件进行杀毒,也可以对某个指定的文件进行杀毒,文件种类包括文本文件TextFile、图片文件ImageFile、视频文件VideoFile。绘制类图并编程实现。

类图:

在这里插入图片描述

代码实现:

public abstract class AbstFile {
    String name;

    public AbstFile(String name) {
        this.name = name;
    }
    public AbstFile(){

    }
    public abstract void display();
    public abstract void add(AbstFile f);
}
//复杂元素
class Folder extends AbstFile {

    ArrayList<AbstFile> list = new ArrayList<>();

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

    @Override
    public void display() {
        System.out.println("对***"+name+"***进行杀毒");
        for (AbstFile f : list) {
            f.display();
        }
    }

    @Override
    public void add(AbstFile f) {
        list.add(f);
    }
}
//简单元素
class ImageFile extends AbstFile {

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

    @Override
    public void display() {
        System.out.println("对***"+name+"***进行杀毒");
    }

    @Override
    public void add(AbstFile f) {
        System.out.println("暂不支持该方法");
    }
}
//简单元素
class TextFile extends AbstFile {

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

    @Override
    public void display() {
        System.out.println("对***"+name+"***进行杀毒");
    }

    @Override
    public void add(AbstFile f) {
        System.out.println("暂不支持该方法");
    }
}
//简单元素
class VideoFile extends AbstFile {

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

    @Override
    public void display() {
        System.out.println("对***"+name+"***进行杀毒");
    }

    @Override
    public void add(AbstFile f) {
        System.out.println("暂不支持该方法");
    }
}
//客户端
public class Client {
    public static void main(String[] args) {
        AbstFile folder = new Folder("我的文件夹");
        AbstFile text = new TextFile("文本文件.txt");
        AbstFile video = new VideoFile("橘生淮南.mp4");
        AbstFile image = new ImageFile("柯南.jpg");
        folder.add(text);
        folder.add(video);
        folder.add(image);
        folder.display();
    }
}

案例3:

给定如图所示的树形结构,请使用组合模式,在客户端完成数据的展示。具体要求如下:

​ 1)绘制组合模式的类图。

​ 2)编写简单元素的代码。

​ 3)编写复杂元素的代码。

​ 4)编写客户端的代码。

提示:程序运行后,输出信息应为Dir1,File1,Dir2,File3,Dir3,File4

在这里插入图片描述

类图:

在这里插入图片描述

简单元素代码:

//简单元素
public class Leaf implements Component {

    String name;

    public Leaf(String name) {
        this.name = name;
    }

    @Override
    public void display() {
        System.out.println(name);
    }

    @Override
    public void add(Component c) {
        System.out.println("暂不支持该方法");
    }

    @Override
    public void remove(Component c) {
        System.out.println("暂不支持该方法");
    }
}

复杂元素代码:

//复杂元素
public class Composite implements Component {

    String name;
    ArrayList<Component> list = new ArrayList<>();

    public Composite(String name) {
        this.name = name;
    }

    @Override
    public void add(Component c) {
        list.add(c);
    }

    @Override
    public void remove(Component c) {
        list.remove(c);
    }

    @Override
    public void display() {
        System.out.println(name);
        for (Component c : list) {
            c.display();
        }
    }
}

客户端代码:

public class Client {
    public static void main(String[] args) {
        Component root = new Composite("Dir1");
        Component comp = new Composite("Dir2");
        Component comp2 = new Composite("Dir3");
        root.add(new Leaf("File1"));
        root.add(comp);
        root.add(comp2);
        comp.add(new Leaf("File3"));
        comp2.add(new Leaf("File4"));
        root.display();
    }
}
外观模式

(应该不会考大题,不是特别重点)

在这里插入图片描述

装饰者模式

装饰者模式:动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)

在这里插入图片描述

具体案例:

​ 请为星巴克公司的饮料销售系统编写一款收费软件。星巴克中可以提供的基础饮料有咖啡、奶茶和可乐,可以选择的配料(Condiment)有布丁(Pudding)、冰激凌(IceCream)、蓝莓(BlueBerry),客户在订购饮料时,可以在基础饮料的基础上添加任意的配料,请使用装饰者模式设计系统,要求绘制系统类图并编写代码,在测试程序中输出一杯添加了布丁和蓝莓的奶茶的价格

在这里插入图片描述

代码实现:

//抽象饮品类
public abstract class Drink {
    
    protected String desc;//描述
    protected int price;//价格

    public abstract int getPrice();
    public abstract String getDesc();
}
//具体的饮料类,咖啡
public class Cofe extends Drink {

    public Cofe(){
        price = 15;
        desc = "咖啡";
    }

    @Override
    public int getPrice() {
        return price;
    }

    @Override
    public String getDesc() {
        return desc;
    }
}
//可乐
public class Cola extends Drink {

    public Cola(){
        price = 17;
        desc = "可乐";
    }

    @Override
    public int getPrice() {
        return price;
    }

    @Override
    public String getDesc() {
        return desc;
    }
}
//奶茶
public class MilkTea extends Drink {

    public MilkTea() {
        price = 16;
        desc = "奶茶";
    }

    @Override
    public int getPrice() {
        return price;
    }

    @Override
    public String getDesc() {
        return desc;
    }
}
//装饰者,抽象配料类
public abstract class Condiment extends Drink{

    protected Drink drink;

    public Condiment(Drink drink){
        this.drink = drink;
    }

}
//具体的配料类,蓝莓
public class BlueBerry extends Condiment {

    public BlueBerry(Drink drink) {
        super(drink);
        desc = "蓝莓";
        price = 5;
    }

    @Override
    public int getPrice() {
        return price + drink.getPrice();
    }

    @Override
    public String getDesc() {
        return drink.getDesc() + "," + desc;
    }
}
//冰淇淋
public class IceCream extends Condiment {

    public IceCream(Drink drink) {
        super(drink);
        desc = "冰淇淋";
        price = 4;
    }

    @Override
    public int getPrice() {
        return price + drink.getPrice();
    }

    @Override
    public String getDesc() {
        return drink.getDesc() + "," + desc;
    }

}
//布丁
public class Pudding extends Condiment {

    public Pudding(Drink drink) {
        super(drink);
        desc = "布丁";
        price = 3;
    }

    @Override
    public int getPrice() {
        return price + drink.getPrice();
    }

    @Override
    public String getDesc() {
        return drink.getDesc() + "," + desc;
    }
}
//客户端使用
public class Client {
    public static void main(String[] args) {
        Drink milkTea = new MilkTea();//16
        milkTea = new Pudding(milkTea);//3
        milkTea = new BlueBerry(milkTea);//5
        System.out.println("描述:" + milkTea.getDesc() + ",价格为:" + milkTea.getPrice());//24
    }
}

行为型设计模式

行为型模式 : 命令模式 , 访问者模式 , 迭代器模式 , 观察者模式 , 责任链模式 , 状态模式 , 策略模式

策略模式

策略模式定义了一系列的算法,将每一个算法封装起来,并且使他们之间可以互相替换。策略模式让算法的变化不会影响到使用算法的客户。

类图

在这里插入图片描述

状态模式

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

设计一个台灯控制软件,台灯上有一个按键和一个旋钮,按键控制电源开关,旋钮控制台灯亮度。请用状态模式实现该控制软件的编写。

1)绘制台灯状态图

2)编写状态类与台灯类

编写测试代码,测试台灯的开关以及亮度的调节

在这里插入图片描述

类图:

在这里插入图片描述

代码实现:

//台灯类
public class Lamp {
    private LampState lampState = new CloseState(this);

    public void clickButton() {
        lampState.clickButton();
    }

    public void brightness() {
        lampState.brightness();
    }
    //动态设置台灯的状态
    public void setLampState(LampState lampState) {
        this.lampState = lampState;
    }
}

//抽象的状态类
public interface LampState {

    public void clickButton();//开关灯

    public void brightness();//调节亮度
}

//具体的状态实现类,开灯状态
class OpenState implements LampState {

    private Lamp lamp;

    public OpenState(Lamp lamp){
        this.lamp = lamp;
    }

    @Override
    public void clickButton() {
        lamp.setLampState(new CloseState(lamp));
    }

    @Override
    public void brightness() {
        System.out.println("开灯状态,变亮!!!!");
    }
}

//具体的状态实现类,关灯状态
class CloseState implements LampState {

    private Lamp lamp;

    public CloseState(Lamp lamp){
        this.lamp = lamp;
    }

    @Override
    public void clickButton() {
        lamp.setLampState(new OpenState(lamp));
    }

    @Override
    public void brightness() {
        System.out.println("关灯状态,调节无效");
    }
}

//客户端
public class Client {
    public static void main(String[] args) {
        Lamp lamp = new Lamp();//默认关灯状态
        lamp.brightness();//调节亮度无效
        lamp.clickButton();//点击按钮,变为开灯状态
        lamp.brightness();//变亮
    }
}
访问者模式

这个比较重要

迭代器模式

观察者模式

定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都得到通知并被自动更新,也叫发布-订阅模式

①主题对象管理着某些数据,一旦数据改变就会通知观察者。

②必须先订阅主题,才能成为主题的观察者。

③也可以取消订阅,就不再是观察者,不再接受通知

在这里插入图片描述

针对数据传递的方式,观察者的实现分为两种:

推式

Subject对象在通知观察者时,只提供一定的参数信息

拉式

Subject对象在通知观察者时,将Subject对象本身提供出去,观察者主动获取感兴趣的参数信息

具体案例:

在这里插入图片描述

代码实现:

//被观察者基类
public class Observable {

    //保存读者(订阅者),
    private ArrayList<Observer> observers = new ArrayList<>();

    public void register(Observer observer) {
        observers.add(observer);
    }

    public void unRegister(Observer observer) {
        observers.remove(observer);
    }

    //通知读者
    public void notifyObservers(){
        for (Observer observer : observers) {
            observer.read(this);
        }
    }
}
//被观察者的具体实现,报纸类
public class Newspaper extends Observable {

    private String name;//报纸名称
    private String info;//报纸内容

    public void setName(String name) {
        this.name = name;
    }
    //设置报纸内容
    public void setInfo(String info) {
        this.info = info;
        //新内容发布时,通知读者
        notifyObservers();
    }

    public String getName() {
        return name;
    }

    public String getInfo() {
        return info;
    }
}
//抽象观察者
public interface Observer {
    public void read(Observable observable);
}
//读者(订阅者,具体的观察者,可以有多个)
public class Reader implements Observer {

    private String username;

    public Reader(String username) {
        this.username = username;
    }

    @Override
    public void read(Observable observable) {
        System.out.println(username + "阅读了" + ((Newspaper) observable).getName()
                + ",内容是" + ((Newspaper) observable).getInfo());
    }
}
//客户端使用
public class Client {
    public static void main(String[] args) {
        Newspaper newspaper = new Newspaper();//创建一个报纸作为被观察者
        Reader r1 = new Reader("张三");//观察者1
        Reader r2 = new Reader("李四");//观察者2
        newspaper.register(r1);//将读者1注册到订阅中
        newspaper.register(r2);

        newspaper.setName("威海日报");
        newspaper.setInfo("惊!哈理工5号楼3楼有众多男生反向拉屎");//发布报纸,更新订阅

        newspaper.unRegister(r1);//将张三取消订阅

        newspaper.setName("成都日报");
        newspaper.setInfo("惊!大学里居然有很多人不会拉屎");
    }
}

设计一个机场信息系统。在该系统中有一个AirPortInfo类负责维持机场信息,例如飞机到达时间、起飞时间、延迟信息、气象信息、航班取消信息等。假设两个依赖于这些信息的类:VoiceInfo类,负责从AirportInfo类自动获取语音机场信息,然后将这些信息传送给乘客;DisplayInfo类,负责从AirportInfo类自动获取文字机场信息,然后将这些信息显示在屏幕上。请使用观察者模式设计该问题,画出类图

在这里插入图片描述

设计一个控制金鱼缸水质、水温与水位高度的软件系统。基本需求:该程序用于自动控制金鱼缸中的水质、水温与水位高度。系统硬件包含鱼缸、化学传感器(ChemSensor)、水温传感器(TempSensor)与水位传感器(LineSensor)。当化学传感器的读数超过某种范围时,鱼缸需要排除部分废水,同事补充新鲜的水;当水温传感器读数低于某温度,或者超过某温度值时,需要开启加热设备或者冷却设备调整水温;当水位读数高于或低于特定高度时,需要开启排水设备,排除部分水或者添加新鲜的水。使用观察者模式设计该软件系统。画出类图

在这里插入图片描述
使用观察者模式设计一个某路口的交通信号灯系统,系统中包含三种角色:分别是信号灯(SignalLight)、汽车(Car)和行人(Person),信号灯可以设置灯的颜色(红-黄-绿),当信号灯颜色发生变化时,汽车和行人可以按照交通规则行动(红灯停,绿灯行,遇到黄灯停一停)

(1)基于JDK对观察者模式的支持,绘制完整项目类图

(2)编写完整代码,并在客户端模拟实现汽车和行人过马路的过程

在这里插入图片描述

代码实现:

//具体的被观察者类,信号灯类
public class SignalLight extends Observable {

    private String lightColor;

    public void setLightColor(String color) {
        lightColor = color;
        setChanged();//设置被观察者中的changed为true
        notifyObservers(color);//通知观察者类状态发生改变
    }
}
//观察者,行人类
public class Person implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        String lightColor = (String) arg;

        if ("yellow".equals(lightColor)){
            awaiting();
        }else if ("red".equals(lightColor)){
            stop();
        }else {
            run();
        }
    }

    public void stop(){
        System.out.println("红灯,person不能通行");
    }

    public void run(){
        System.out.println("绿灯,person可以通行");
    }

    public void awaiting(){
        System.out.println("黄灯,person需要等待一会");
    }
}
//观察者,车类
public class Car implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        String lightColor = (String) arg;
        /*((SignalLight)o)*/
        if ("yellow".equals(lightColor)){
            awaiting();
        }else if ("red".equals(lightColor)){
            stop();
        }else {
            run();
        }
    }

    public void stop(){
        System.out.println("红灯,car不能通行");
    }

    public void run(){
        System.out.println("绿灯,car可以通行");
    }

    public void awaiting(){
        System.out.println("黄灯,car需要等待一会");
    }
}
//客户端
public class Client {
    public static void main(String[] args) {
        //创建被观察者实例
        SignalLight light = new SignalLight();
        //向集合中添加多个观察者
        light.addObserver(new Car());
        light.addObserver(new Person());
        //设置灯的状态
        light.setLightColor("red");
        light.setLightColor("yellow");
        light.setLightColor("green");
    }
}
责任链模式

基本类图

在这里插入图片描述

案例:

实现学生请假流程。 学生向老师提出请假申请,包含请假理由和请假天数。 如果天数在3天以内, 可以由老师批复, 如果天数在4天以上,10天以内可以由主任批复, 如果天数超过10天, 则要由校长批复

类图:

在这里插入图片描述

代码:

//学生请假条
public class Request {
    private String desc;
    private int day = 0;

    public Request(String desc, int day) {
        this.desc = desc;
        this.day = day;
    }

    public String getDesc() {
        return desc;
    }

    public int getDay() {
        return day;
    }
}
//抽象的处理者
public abstract class Handler {
    protected Handler successor;
    protected String name;

    public Handler(String name) {
        this.name = name;
    }

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    public abstract void handlerRequest(Request request);
}

class Teacher extends Handler {

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

    @Override
    public void handlerRequest(Request request) {
        if (request.getDay() <= 3) {
            System.out.println("请假内容为:" + request.getDesc() + "," + name + "已审批");
        } else {
            successor.handlerRequest(request);
        }
    }
}
//主任
class Director extends Handler {

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

    @Override
    public void handlerRequest(Request request) {
        if (request.getDay() >= 4 && request.getDay() <= 10) {
            System.out.println("请假内容为:" + request.getDesc() + "," + name + "已审批");
        } else {
            successor.handlerRequest(request);
        }
    }
}

class SchoolManster extends Handler {

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

    @Override
    public void handlerRequest(Request request) {
        if (request.getDay() > 10) {
            System.out.println("请假内容为:" + request.getDesc() + "," + name + "已审批");
        } else {
            successor.handlerRequest(request);
        }
    }
}
//客户端
public class Client {
    public static void main(String[] args) {
        Request request = new Request("家中有事", 9);

        Handler t = new Teacher("李老师");
        Handler d = new Director("秦主任");
        Handler s = new SchoolManster("孙校长");

        t.setSuccessor(d);
        d.setSuccessor(s);
        s.setSuccessor(t);

        t.handlerRequest(request);
    }
}

软件体系结构

SOA架构

绘制 SOA 架构图并描述 SOA 的工作机制,并说明 Web Service 中用什么语言来描述服务

架构图:

在这里插入图片描述

工作机制:

1)服务的提供者将要暴露的服务注册到公共的服务注册器中。

2)服务消费者查询服务注册器,寻找符合需求的服务。如果服务注册器中有这样的服务,它将为消费者提供该服务的描述信息(服务合同)

3)服务消费者与服务提供者将直接绑定,服务提供者开始为服务消费者执行相应的服务。

Web Service使用WSDL描述服务

绘制 MVC 体系结构逻辑示意图,并列举出软件开发中至少两个应用了 MVC思想的开发模型

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

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抽象工厂模式(Abstract Factory Pattern) 引入: 在前面介绍的两个创建型模式里面,我们解决的都是有关"new"的问题,用它们来避免显式指定类创建对象。我写的也非常简单易懂,相信看过的朋友们都应该对简单工厂模式、工厂方法模式的意图、所能解决的问题及适用情景有一定的了解了。但是若要达到灵活运用,什么时候用,怎样用合适还不是看一篇文章就能解决的问题。呵呵..这需要你对OO的理解程度,你的项目开发经验等等许多方面的积累。一起努力喔。。 好了,咱们言归正传,通过对这两个模式的了解,我们掌握一种思想,就是在创建一个对象时,需要把容易发生变化的地方给封装起来,来控制变化(哪里变化,封装哪里),以适应客户的变动,项目的扩展。但是,我们在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作,同时由于需求的变化,这“一系列相互依赖的对象”也要改变,如何应对这种变化呢?如何像简单工厂模式、工厂方法模式一样绕过常规的"new",然后提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合?可能有人会说,你也可以将这些对象一个一个通过工厂方法模式来解决呀?但是,我们试想,既然是一系列相互依赖的对象,它们是有联系的,每个对象都这样解决,你又如何来保证他们的联系呢?举一个例子:Windows桌面主题,当你更换一个桌面主题的时候,系统的开始按钮、任务栏、菜单栏、工具栏等等都变了,而且是一起变的,他们的色调都还很一致,难道类似这样的问题,怎么来解决呢?它的天敌就是抽象工厂模式。 意图: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 参考者: 也就是该模式中的各个类或对象之间的关系: 抽象工厂(Abstract Factory) 声明生成一系列抽象产品的方法 具体工厂(Concrete Factory) 执行生成一系列抽象产品的方法,生成一系列具体的产品 抽象产品(Abstract Product) 为这一系列的某一种产品声明接口 具体产品(Product) 定义具体工厂生成的具体产品的对象,实现产品接口 客户(Client) 我们的应用程序客户端(不要理解成人),使用抽象产品和抽象工厂生成对象。 抽象工厂模式UML图 抽象工厂模式在生活中的实例 咱们继续拿怎么穿衣服来说明这个抽象工厂模式。 就拿你来说吧。工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。咱们假设一种情况(现实中是不存在的,要不然,没法进入共产主义了,但有利于说明抽象工厂模式),在你的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用OO的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。 分析: 要好好去读上面那个实例,虽然有点绕嘴,其实只要用心去读,分清了抽象工厂模式的各个角色,对理解设计模式是非常重要的。理解头绪,然后接合简单工厂模式、工厂方法模式对工厂家族的了解,再加上抽象工厂模式的意图,头脑中差不多有一个雏型了吧。好了,咱们一起来分析一下。。 先把各个角色揪出来。 抽象工厂:虚拟的衣柜,它只是个概念而已。在项目中可能是一个接口或抽象类,定义规则,取出上衣,裤子。 具体工厂:具体的存在的衣柜,它用于存放某一种成套的衣服,换句话说,这种成套的衣服都是从这个衣柜中取出的。在项 目中继承于抽象工厂,实现抽象工厂中的方法,取出具体产品,某一件上衣,某一条裤子。 抽象产品:虚拟的衣服,也只是个概念。在项目中可能是多个接口或抽象类,定义规则,有什么特性,起什么作用。 具体产品:具体的实际存在的产品,它指的就是用于组装成某一套衣服的某一件上衣或裤子。它继承自某一个抽象产品。实 现抽象产品中制定的规则,特性。 它们之间怎么联系呢?客户在用的时候,依赖的又是什么呢? 客户在要的时候,首先要说出你要的什么系列的衣服,然后根据它的要求生成一个具体工厂的实例,剩下的工作就都是这个倒霉的具体工厂了,它会根据自己的实现生成一个上衣,生成一个裤子,然后把它交给客户。客户在这一过程中并不知道具体工厂都了什么。也就是说,客户只依赖于抽象工厂和抽象产品了。在初始化的时候会用到一次具体工厂类名,我们根据.NET特有的反射机制又可以把这个在客户端唯一的具体的非抽象类放到一个应用程序配置文件中,防止它变化。 这就符合了设计模式中的“开放--封闭”原则,依赖倒转原则,里氏代换原则等等。 具体代码如下: 抽象工厂角色: 1namespace AbstractFactory 2{ 3 //抽象工厂类, 4 public abstract class AbstractClothes 5 { 6 //抽象方法:创建一个上衣 7 abstract public AbstractCoat CreateCoat(); 8 //抽象方法:创建一个裤子 9 abstract public AbstractTrousers CreateTrousers(); 10 } 11} 12 抽象产品角色: 1namespace AbstractFactory 2{ 3 /**//// <summary> 4 /// 抽象产品----上衣抽象类 5 /// </summary> 6 public abstract class AbstractCoat 7 { 8 //性别属性 9 public abstract bool Sex 10 { 11 get; 12 } 13 14 //样式属性 15 public abstract string Style 16 { 17 get; 18 } 19 } 20 21 /**//// <summary> 22 /// 抽象产品----裤子抽象类 23 /// </summary> 24 public abstract class AbstractTrousers 25 { 26 //性别属性 27 public abstract bool Sex 28 { 29 get; 30 } 31 32 //样式属性 33 public abstract string Style 34 { 35 get; 36 } 37 } 38} 39 具体工厂角色: 1namespace AbstractFactory 2{ 3 /**//// <summary> 4 ///时尚男装 5 /// </summary> 6 public class FashionManClothes:AbstractClothes 7 { 8 public override AbstractFactory.AbstractCoat CreateCoat() 9 { 10 return new CoatA(); 11 } 12 13 public override AbstractTrousers CreateTrousers() 14 { 15 return new TrousersA(); 16 } 17 } 18 19 /**//// <summary> 20 /// 时尚女装 21 /// </summary> 22 public class FashionWomanClothes : AbstractClothes 23 { 24 public override AbstractCoat CreateCoat() 25 { 26 return new CoatB(); 27 //throw new Exception("The method or operation is not implemented."); 28 } 29 public override AbstractTrousers CreateTrousers() 30 { 31 return new TrousersB(); 32 //throw new Exception("The method or operation is not implemented."); 33 } 34 } 35} 具体产品角色:(注意:我并没有把所有的具体产品类都列出来,由于简单,可以推想出剩余的产品类,详见附件) 1namespace AbstractFactory 2{ 3 /**//// <summary> 4 /// 时尚男性上衣 5 /// </summary> 6 public class CoatA:AbstractFactory.AbstractCoat 7 { 8 private bool sex = true; 9 private string style = "时尚"; 10 /**//// <summary> 11 /// 重写基类的Sex属性 12 /// </summary> 13 public override bool Sex 14 { 15 get 16 { 17 return sex; 18 } 19 } 20 21 /**//// <summary> 22 /// 重写基类的Style属性 23 /// </summary> 24 public override string Style 25 { 26 get 27 { 28 return style; 29 } 30 } 31 } 32 33 /**//// <summary> 34 /// 时尚男性裤子 35 /// </summary> 36 public class TrousersA : AbstractTrousers 37 { 38 private bool sex = true; 39 private string style = "时尚"; 40 public override bool Sex 41 { 42 get 43 { 44 return sex; 45 } 46 } 47 public override string Style 48 { 49 get 50 { 51 return style; 52 } 53 } 54 } 55} 客户端代码: 1namespace AbstractFactory 2{ 3 /**//// <summary> 4 /// 创建衣服类 5 /// </summary> 6 public class CreateClothes 7 { 8 private AbstractCoat myCoat; 9 private AbstractTrousers myTrousers; 10 public CreateClothes(AbstractClothes clothes) 11 { 12 myCoat = clothes.CreateCoat(); 13 myTrousers = clothes.CreateTrousers(); 14 } 15 16 public void ShowMyClothes() 17 { 18 Console.WriteLine("My Clothes:"); 19 string sex= myCoat.Sex ? "男" : "女"; 20 //Console.WriteLine("Coat:{0} {1}", myCoat.Sex ? "男" : "女", myCoat.Style); 21 Console.WriteLine("Coat:{0} {1}", sex, myCoat.Style); 22 sex=myTrousers.Sex?"男":"女"; 23 Console.WriteLine("Trousers:{0} {1}", sex, myTrousers.Style); 24 } 25 } 26 27 28 public class Client 29 { 30 static void Main(string[] args) 31 { 32 //创建一个工厂类的实例 33 string assemblyName = ConfigurationManager.AppSettings["assemblyName"]; 34 string fullTypeName =string.Concat( ConfigurationManager.AppSettings["nameSpaceName"] ,".", ConfigurationManager.AppSettings["typename"]); 35 36 AbstractClothes factory = (AbstractClothes)Assembly.Load(assemblyName).CreateInstance(fullTypeName); 37 CreateClothes clothes = new CreateClothes(factory); 38 clothes.ShowMyClothes(); 39 Console.Read(); 40 } 41 } 42} 43 app.config文件 1<configuration> 2 <appSettings> 3 <!--一般情况下只需改第三个"typename"就行了,具体工厂类 --> 4 <add key="assemblyName" value="ConcreteFactory"/> 5 <add key="nameSpaceName" value="AbstractFactory"/> 6 <add key="typename" value="FashionManClothes"/> 7 </appSettings> 8</configuration>
实验一 单例模式的应用 1 实验目的 1) 掌握单例模式(Singleton)的特点 2) 分析具体问题,使用单例模式进行设计。 2 实验内容和要求 很多应用项目都有配置文件,这些配置文件里面定义一些应用需要的参数数据。 通常客户端使用这个类是通过new一个AppConfig的实例来得到一个操作配置文件内容 的对象。如果在系统运行中,有很多地方都需要使用配置文件的内容,系统中会同时存 在多份配置文件的内容,这会严重浪费内存资源。 事实上,对于AppConfig类,在运行期间,只需要一个对象实例就够了。那么应该怎 么实现呢?用C#控制台应用程序实现该单例模式。绘制该模式的UML图。 3 模式结构图 4 UML类图 5 代码 6运行结果 实验二 工厂模式的应用 1 实验目的 1) 掌握工厂模式(Factory)的特点 2) 分析具体问题,使用工厂模式进行设计。 2 实验内容和要求 有一个OEM制造商代理HP笔记本电脑(Laptop),后来该制造商得到了更多的品牌笔 记本电脑的订单Acer,Lenovo,Dell,该OEM商发现,如果一次同时很多个牌子的本本 ,有些不利于管理。利用工厂模式改善设计,用C#控制台应用程序实现该OEM制造商的工 厂模式。绘制该模式的UML图。 3 模式结构图 4 UML类图 5 代码 6运行结果 实验三 抽象工厂模式的应用 1 实验目的 1) 掌握抽象工厂模式(Abstract Factory)的特点 2) 分析具体问题,使用抽象工厂模式进行设计。 2 实验内容和要求 麦当劳(McDonalds)和肯德基(KFC)快餐店都经营汉堡(Hamburg)和可乐(Cola ),用C#控制台应用程序实现这两个快餐店经营产品的抽象工厂模式。绘制该模式的UM L图。 3 模式结构图 4 UML类图 5代码 6运行结果 df 实验四 建造者模式的应用 1 实验目的 1) 掌握建造者模式(Builder)的特点 2) 分析具体问题,使用建造者模式进行设计。 2 实验内容和要求 建造者模式是一种创建型模式,它主要是应对项目中一些复杂对象的创建工作。所谓 "复杂对象",是指此对象中还含有其它的子对象。我们现在定义一个场景:汽车生产必 须包含车轮(Wheel)、油箱(OilBox)和车身(Body),应用建造者模式,用C#控制台应用程 序实现该设计,构建BMW品牌和BenZ品牌汽车生产。绘制该模式的UML图。 3 模式结构图 4 UML类图 5代码 6运行结果 实验五 适配器模式的应用 1 实验目的 1) 掌握适配器模式(Adapter)的特点 2) 分析具体问题,使用适配器模式进行设计。 2 实验内容和要求 一个软件团队开发绘图系统,设计了圆对象(Circle)、矩形对象(Rectangle),线对 象(Line)都支持Draw()函数,即可以通过Draw()函数绘制图形。为了加快项目进度,将 角度对象(Angle)绘制功能交给了合作团队实现。但合作团队将角度对象绘制函数定为了 DrawAngle()。绘图系统提供给用户后,用户不满意,希望能统一的调用,不用记太多命 令。应用适配器模式,用C#控制台应用程序完善该设计。绘制该模式的UML图。 3模式结构图 4 UML类图 5 代码 6运行结果 实验六 桥接模式的应用 1 实验目的 1) 掌握桥接模式(Bridge)的特点 2) 分析具体问题,使用桥接模式进行设计。 2 实验内容和要求 一个咖啡店可以提供大杯(JorumCoffee)、中杯(MediumCoffee)、小杯(SmallCoffee )的咖啡(Coffee),为了满足不同用户的口味,在咖啡中可以添加牛奶(Milk),或者糖( Sugar),或者柠檬(Lemon),提供给用户不同口味的组合,如大杯咖啡加牛奶,中杯咖啡 加糖,小杯咖啡加柠檬,小杯咖啡加糖等。应用桥接模式,用C#控制台应用程序实现该 设计。绘制该模式的UML图。 3 模式结构图 4 UML类图 5 代码 6 运行结果 实验七 装饰模式的应用 1 实验目的 1) 掌握装饰模式(Decorator)的特点 2) 分析具体问题,使用装饰模式进行设计。 2 实验内容和要求 "喜羊羊逃命"游戏:喜羊羊被灰太狼追,喜羊羊最多5条命,灰太狼每咬到喜羊羊一 次,喜羊羊就要少一条命。在逃的过程中喜羊羊可以吃到三种苹果,吃"红苹果"可以给 喜羊羊加上保护罩,吃"绿苹果"可以加快喜羊羊奔跑速度,吃"黄苹果"可以使喜羊羊趟 着水跑。应用装饰模式,用C#控制台应用程序实现该设计。绘制该模式的UML图。 提示:这个例子如果用类的继承来实现的话那可就麻烦了,你需要为喜羊羊派生3*2 *1=6个子类(有保护罩的喜羊羊,奔跑速度加快的喜羊羊,会趟水的喜羊羊,既有保护 罩又会趟水的喜

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值