admin管理员组文章数量:1530080
七个设计原则
设计原则核心思想:
1) 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
2) 针对接口编程,而不是针对实现编程。
3) 为了交互对象之间的松耦合设计而努力
单一职责原则
定义:
就一个类而言,应该只有一个引起它变化的原因
理解:
对于相同的功能,不要散落在各个类中(内聚性)
一个类的职责单一(低耦合)
接口隔离原则
定义:
客户端不应该依赖它不需要的接口
重构:
把接口细分为更小的接口
依赖倒转原则
定义
高层模块不应该依赖低层模块,二者都应该依赖其抽象
抽象不应该依赖细节,细节应该依赖抽象
依赖体现:
调用、继承、实现
里氏替换原则
定义:
子类型必须能够替换父类型,且功能保持不变;尽量不重写,重载父类方法,来改变程序功能
开闭原则
定义:
一个软件实体应该对扩展开放,对修改关闭
理解:
满足客户新的需求扩展功能
扩展同时不修改原有代码
实现关键:
抽象(抽象类、接口)
实现方法:
对于发生变化的功能进行抽象形成接口,给接口以不同实现
模块间的调用通过接口进行
迪米特法则
定义:
一个对象应该对其他对象保持最少的了解
只与它的直接朋友通信
朋友:
两个对象之间存在耦合关系称之为直接朋友,局部变量不是直接朋友
合成复用原则
定义:
尽量少用继承,多用组合聚合实现复用
23种设计模式
创建型模式 : 单例模式 , 抽象工厂模式 , 原型模式 , 建造者模式 , 工厂模式
结构型模式 : 适配器模式 , 桥接模式 , 装饰模式 , 组合模式 , 外观模式 , 享元模式 , 代理模式
行为型模式 : 模板方法模式 , 命令模式 , 访问者模式 , 迭代器模式 , 观察者模式 , 中介者模式 , 备忘录模式 , 解释器模式 , 状态模式 , 策略模式 , 职责链模式
创建型设计模式
创建型模式 : 单例模式 , 抽象工厂模式 , 原型模式 , 建造者模式 , 工厂模式
单例模式
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。
饿汉式(静态常量)应用实例 步骤如下:
构造器私有化 (防止 new )
类的内部创建对象
向外暴露一个静态的公共方法
getInstance ()
;代码实现
单例模式注意事项和细节说明
- 单例模式保证了 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
- 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用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)获得子类
一、有一个OEM制造商代理做HP笔记本(Laptop),后来该制造商得到了更多的品牌笔记本电脑的订单Acer,Lenovo,Dell,该OEM商发现,如果一次同时做很多个牌子的本本,有些不利于管理。利用工厂模式改善设计,用java控制台应用程序实现该OEM制造商的工厂模式。
UML类图
//工厂方法模式
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 MedGameFactory4、描述新的设计类图;
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类
一个抽象工厂类,可以派生出多个具体工厂类
每个具体工厂类可以创建多个具体产品类的实例,也就是创建的是一个产品线下的多个产品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(); } }
建造者模式
-
建造者模式(Builder Pattern) 又叫生成器模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。
-
建造者模式 是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。
建造者模式的四个角色
- Product(产品角色): 一个具体的产品对象。
- Builder(抽象建造者): 创建一个Product对象的各个部件指定的 接口/抽象类。
- ConcreteBuilder(具体建造者): 实现接口,构建和装配各个部件。
- 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());
}
}
建造者模式的注意事项和细节
-
客户端(使用程序)不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象
-
每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象
-
可以更加精细地控制产品的创建过程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程
-
增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合 “开闭原则”
-
建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
-
如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,因此在这种情况下,要考虑是否选择建造者模式.
在例2.5的设计中,添加一个经济型房屋生成器类,命名为EconHouseBuilder。注意经济型房屋的面积比较小,卧室、卫生间和车库的数量较少,切不包含花园和游泳池。设计并且写出实现代码,具体要求参见光盘的相应作业部分
原型模式
原型模式(Prototype模式)是指:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象
原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节
工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建,即 对象.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:通过对象序列化实现深拷贝
结构型设计模式
结构型模式 : 适配器模式 , 桥接模式 , 装饰者模式 , 组合模式 , 外观模式 , 代理模式
适配器模式
-
适配器模式(Adapter Pattern)将某个类的接口转换成客户端期望的另一个接口表示,主的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器(Wrapper)
-
适配器模式属于结构型模式
-
主要分为三类:类适配器模式、对象适配器模式
类适配器
以充电头案例为例,插座的电压是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思想的开发模型
版权声明:本文标题:软件设计模式 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1726615153a1078150.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论