设计模式 Ⅱ
08. 装饰模式
在某咖啡店,用户可以在选择茶或者咖啡作为基础饮料,还可以任意添加红糖、奶油、冰糖等料,请用装饰器模式实现该店饮料计费系统,以便能方便的计算不同类型的饮料价格。使用装饰模式设计该系统,绘制类图并编程实现。
模式结构图
实现代码
/* 抽象构件类Billing */
public interface Billing {
public float cost();
}
/* 具体构建类Tea */
public class Tea implements Billing {
private Billing billing;
public Tea(){
System.out.println("----- 欢迎光临本咖啡店 -----");
System.out.println("----- 您选择了茶底 -----");
}
@Override
public float cost() {
// TODO Auto-generated method stub
return 10;
}
}
/* 具体构建类Coffee */
public class Coffee implements Billing {
private Billing billing;
public Coffee(){
System.out.println("----- 欢迎光临本咖啡店 -----");
System.out.println("----- 您选择了咖啡底 -----");
}
@Override
public float cost() {
// TODO Auto-generated method stub
return 15;
}
}
/* 抽象装饰类 */
public class Ingredients implements Billing {
private Billing billing;
public Ingredients(Billing billing){
super();
this.billing = billing;
}
@Override
public float cost() {
// TODO Auto-generated method stub
return billing.cost();
}
}
/* 具体装饰类Suger */
public class Suger extends Ingredients{
public Suger(Billing billing) {
super(billing);
System.out.println("----- 您选择了加糖 -----");
}
public float cost(){
return 2 + super.cost();
}
}
/* 具体装饰类Cream */
public class Cream extends Ingredients{
public Cream(Billing billing) {
super(billing);
System.out.println("----- 您选择了加奶霜 -----");
}
public float cost(){
return 5 + super.cost();
}
}
/* 具体装饰类Pearl */
public class Pearl extends Ingredients{
public Pearl(Billing billing) {
super(billing);
System.out.println("----- 您选择了加珍珠 -----");
}
public float cost(){
return 3 + super.cost();
}
}
/* 客户端测试类Client */
public class Client {
public static void main(String[] args) {
Billing b;
b = new Coffee();
b.cost();
Suger i = new Suger(b);
i.cost();
System.out.println("----- 一共消费:"+i.cost()+"元 -----");
}
}
结果截图
09. 代理模式
请结合JDK完成一个动态代理的案例,绘制类图并编程实现。
模式结构图
实现代码
/* 抽象权限类AbstractPremission */
public interface AbstractPremission {
public void viewNote();
public void publishNote();
public void setLevel(int level);
}
/* 真实权限类RealPermission */
public class RealPermission implements AbstractPremission {
@Override
public void viewNote() {
// TODO Auto-generated method stub
}
@Override
public void publishNote() {
// TODO Auto-generated method stub
System.out.println("发布新帖!");
}
@Override
public void setLevel(int level) {
// TODO Auto-generated method stub
}
}
/* 权限代理类PermissionProxy */
public class PermissionProxy implements AbstractPremission {
private RealPermission permission = new RealPermission();
private int level = 0 ;
@Override
public void viewNote() {
// TODO Auto-generated method stub
System.out.println("查看帖子!");
}
@Override
public void publishNote() {
// TODO Auto-generated method stub
if (0 == level) {
System.out.println("对不起,您没有该权限!");
}
else if (1 == level) {
permission.publishNote();
}
}
@Override
public void setLevel(int level) {
// TODO Auto-generated method stub
this.level = level;
}
}
/* 客户端测试类Client */
public class Client {
public static void main(String[] args) {
AbstractPremission permission = new PermissionProxy();
permission.viewNote();
permission.publishNote();
System.out.println("-----------------");
permission.setLevel(1);
permission.viewNote();
permission.publishNote();
}
}
结果截图
10. 外观模式
在电脑主机(Mainframe)中,只需要按下主机的开机按钮(on()),即可调用其他硬件设备和软件的启动方法,如内存(Memory)的自检(check()),CPU的运行(run()),硬盘(HardDisk)的读取(read()),操作系统(OS)的载入(load())等,如果某一过程发生错误则电脑启动失败。使用外观模式模拟该过程,绘制类图并编程实现。
模式结构图
实现代码
/* 子系统类Memory */
public class Memory {
public static void check(){
System.out.println("内存正在自检……");
}
public void on(){
System.out.println("CPU开始运行!");
Memory.check();
}
public void off(){
System.out.println("内存停止运行!");
}
}
/* 子系统类CPU */
public class CPU {
public static void run(){
System.out.println("CPU正在运行……");
}
public void on(){
System.out.println("CPU开始运行!");
CPU.run();
}
public void off(){
System.out.println("CPU停止运行!");
}
}
/* 子系统类HardDisk */
public class HardDisk {
public static void read(){
System.out.println("硬盘正在读取……");
}
public void on(){
System.out.println("硬盘开始运行!");
HardDisk.read();
}
public void off(){
System.out.println("硬盘停止运行!");
}
}
/* 子系统类OS */
public class OS {
public static void load(){
System.out.println("操作系统正在载入……");
}
public void on(){
System.out.println("操作系统开始运行!");
OS.load();
}
public void off(){
System.out.println("操作系统停止运行!");
}
}
/* 外观类Mainframe */
public class Mainframe {
private Memory memory;
private CPU cpu;
private HardDisk hardDisk;
private OS os;
public Mainframe(){
memory = new Memory();
cpu = new CPU();
hardDisk = new HardDisk();
os = new OS();
}
public void on(){
memory.on();
cpu.on();
hardDisk.on();
os.on();
}
public void off(){
memory.off();
cpu.off();
hardDisk.off();
os.off();
}
}
/* 客户端测试类Client */
public class Client {
public static void main(String[] args) {
Mainframe mf = new Mainframe();
mf.on();
System.out.println("-----------------");
mf.off();
}
}
结果截图
11. 命令模式
某软件公司欲开发一个基于Windows平台的公告板系统。系统提供一个主菜单(Menu),在主菜单中包含了一些菜单项(MenuItem),可以通过Menu类的addMenuItem()方法增加菜单项。菜单项的主要方法是click(),每一个菜单项包含一个抽象命令类,具体命令类包括OpenCommand(打开命令),CreateCommand(新建命令),EditCommand(编辑命令)等,命令类具有一个execute()方法,用于调用公告板系统界面类(BoardScreen)的open()、create()、edit()等方法。现使用命令模式设计该系统,使得MenuItem类与BoardScreen类的耦合度降低,绘制类图并编程实现。
模式结构图
实现代码
import java.util.ArrayList;
import java.util.List;
/* 接收者类Menu */
public class Menu {
private List<MenuItem> menuList=new ArrayList();
public void addMenuItem(MenuItem MenuItem) {
menuList.add(MenuItem);
}
public MenuItem getMenuItem(int index) {
return menuList.get(index);
}
}
/* 调用者类MenuItem */
public class MenuItem {
private Command openCommand=null;
private Command createCommand=null;
private Command editCommand=null;
MenuItem(Command openCommand,Command createCommmand,Command editCommand){
this.openCommand=openCommand;
this.createCommand=createCommmand;
this.editCommand=editCommand;
}
public void openC(){
openCommand.execute();
}
public void createC(){
createCommand.execute();
}
public void editC(){
editCommand.execute();
}
}
/* 抽象命令类Command */
public interface Command {
public void execute();
}
/* 公告板系统界面类BoardScreen */
public class BoardScreen {
public void open() {
System.out.println("公告板系统界面类中open()被调用");
}
public void create() {
System.out.println("公告板系统界面类中create()被调用");
}
public void edit() {
System.out.println("公告板系统界面类中edit()被调用");
}
}
/* 具体命令类CreateCommand */
public class CreateCommand implements Command {
private BoardScreen boardscreen;
@Override
public void execute() {
boardscreen.create();
}
public CreateCommand(BoardScreen boardScreen){
this.boardscreen = boardScreen;
}
}
/* 具体命令类EditCommand */
public class EditCommand implements Command {
private BoardScreen boardscreen;
@Override
public void execute() {
boardscreen.edit();
}
public EditCommand(BoardScreen boardScreen){
this.boardscreen=boardScreen;
}
}
/* 具体命令类OpenCommand */
public class OpenCommand implements Command {
private BoardScreen boardscreen;
@Override
public void execute() {
boardscreen.open();
}
public OpenCommand(BoardScreen boardScreen){
this.boardscreen = boardScreen;
}
}
/* 客户端测试类Client */
public class Client {
public static void main(String args[]) {
//接受者
BoardScreen boardScreen=new BoardScreen();
Menu menu=new Menu();
//命令对象
OpenCommand open=new OpenCommand(boardScreen);
CreateCommand create=new CreateCommand(boardScreen);
EditCommand edit=new EditCommand(boardScreen);
//请求者
MenuItem menuItem=new MenuItem(open,create,edit);
menu.addMenuItem(menuItem);
//测试
menuItem.createC();
menuItem.editC();
menuItem.openC();
}
}
结果截图
12. 观察者模式
某在线股票软件需要提供如下功能:当股票购买者所购买的某支股票价格变化幅度达到5%时,系统将自动发送通知(包括新价格)给购买该股票的股民。现使用观察者模式设计该系统,绘制类图并编程实现。
模式结构图
实现代码
import java.util.ArrayList;
/* 抽象目标类Shares */
public abstract class Shares {
protected ArrayList<SharesPeople> people = new ArrayList<SharesPeople>();
public void attach(SharesPeople sharespeople){
people.add(sharespeople);
}
public void remove(SharesPeople sharespeople){
people.remove(sharespeople);
}
public abstract void notifyPeople(int num);
}
/* 抽象观察者类SharesListener */
public interface SharesListener {
void response();
}
/* 具体目标类SharesEvent */
public class SharesEvent extends Shares {
@Override
public void notifyPeople(int num) {
if(num>=5){
for(Object obj:people){
System.out.print("股票变化:");
((SharesPeople)obj).response();
}
}else{
System.out.print("股票变化:");
System.out.println("正常");
}
}
}
/* 具体观察者类SharesPeople */
public class SharesPeople implements SharesListener {
private String name;
public SharesPeople(String name){
this.name= name;
}
@Override
public void response() {
// TODO Auto-generated method stub
System.out.println("正在发送通知股民成员:"+name+",股票价格变化幅度达到5%..");
System.out.println(name+"已收到通知");
}
}
/* 客户端测试类Client */
public class Client {
public static void main(String args[]){
Shares shares = new SharesEvent();
SharesPeople sp1 = new SharesPeople("张三");
SharesPeople sp2 = new SharesPeople("李四");
SharesPeople sp3 = new SharesPeople("王五");
shares.attach(sp1);
shares.attach(sp2);
shares.attach(sp3);
shares.notifyPeople(1);
shares.notifyPeople(2);
shares.notifyPeople(3);
shares.notifyPeople(5);
}
}
结果截图
13. 策略模式
设计一个网上书店,该系统中所有的计算机类图书(ComputerBook)每本都有10%的折扣,所有的语言类图书(LanguageBook) 每本都有2元的折扣,小说类图书(NovelBook)每100元有10元的折扣。现使用策略模式来设计该系统,绘制类图并编程实现。
模式结构图
实现代码
/* 抽象策略类BookStrategy */
public interface BookStrategy {
double calPrice(double price);
}
/* 具体策略类ComputerBook */
public class ComputerBook implements BookStrategy {
@Override
public double calPrice(double price) {
System.out.println("所有的计算机图书 每本都有10%的折扣");
return price*0.9D;
}
public ComputerBook(){
}
}
/* 具体策略类LanguageBook */
public class LanguageBook implements BookStrategy {
@Override
public double calPrice(double price) {
System.out.println("语言类图书 每本有2元的折扣");
return price-2.0D;
}
public LanguageBook(){
}
}
/* 具体策略类NovelBook */
public class NovelBook implements BookStrategy {
@Override
public double calPrice(double price) {
System.out.println("小说类图书以每100元有10元的折扣");
int p = (int) price;
return price-(double)(p/100*10);
}
public NovelBook(){
}
}
/* 环境类Price */
public class Price {
private BookStrategy bookStrategy;
public Price(BookStrategy bookStrategy){
this.bookStrategy = bookStrategy;
}
public double sum(double price){
return this.bookStrategy.calPrice(price);
}
}
/* 客户端测试类Client */
public class Client {
public static void main(String[] args) {
//定义具体的打折策略
ComputerBook computerBook = new ComputerBook();
LanguageBook languageBook = new LanguageBook();
NovelBook novelBook = new NovelBook();
//原价 折后价
double price = 500.0D;
double discountPrice;
//计算机书籍打折策略
System.out.println("==========计算机书籍打折策略==========");
System.out.println("打折前的价格为:"+price);
discountPrice = new Price(computerBook).sum(price);
System.out.println("打折后的价格为:"+discountPrice);
//语言书籍打折策略
System.out.println("==========语言书籍打折策略==========");
System.out.println("打折前的价格为:"+price);
discountPrice = new Price(languageBook).sum(price);
System.out.println("打折后的价格为:"+discountPrice);
//小说书籍打折策略
System.out.println("==========小说书籍打折策略==========");
System.out.println("打折前的价格为:"+price);
discountPrice = new Price(novelBook).sum(price);
System.out.println("打折后的价格为:"+discountPrice);
}
}