动机(Motivation)
模式定义
要点总结
结构图
//享元接口
interface IFlyweight{
void doSomething();
}
//具体享元
class Flyweight implements IFlyweight{
private String value;
public Flyweight(String value){
this.value = value;
}
@Override
public void doSomething() {
System.out.println(value);
}
}
//享元工厂
class FlyweightFactory{
HashMap<String, IFlyweight> flyweights = new HashMap<String, IFlyweight>();
IFlyweight getFlyweight(String value){
IFlyweight flyweight = flyweights.get(value);
if(flyweight == null){
flyweight = new Flyweight(value);
flyweights.put(value, flyweight);
}
return flyweight;
}
public int size(){
return flyweights.size();
}
}
//简单的享元模式
public class SimpleFlyweight {
public static void main(String args[]){
FlyweightFactory factory = new FlyweightFactory();
IFlyweight flyweight1,flyweight2,flyweight3,flyweight4;
flyweight1 = factory.getFlyweight("value1");
flyweight2 = factory.getFlyweight("value1");
flyweight3 = factory.getFlyweight("value1");
flyweight4 = factory.getFlyweight("value2");
flyweight1.doSomething();
flyweight2.doSomething();
flyweight3.doSomething();
flyweight4.doSomething();
System.out.println(factory.size());
}
}
动机(Motivation)
模式定义
要点总结
示例代码很简单,这里不做过多说明,其中ProductSalesman
类就是门面模式中的门面(Facade)
//计算优惠
public class Discount {
int getDiscount(String discountCode){
return Math.abs(discountCode.hashCode())%3;
}
}
//计费子系统
public class FinalPrice {
ProductPrice productPrice;
Postage postage;
Discount discount;
public FinalPrice(){
productPrice = new ProductPrice();
postage = new Postage();
discount = new Discount();
}
int getFinalPrice(String product,String addr,String discountCode){
return productPrice.getPrice(product)+postage.getPostage(addr)-discount.getDiscount(discountCode);
}
}
//计算邮费
public class Postage {
int getPostage(String addr){
return Math.abs(addr.hashCode())%20+6;//模拟邮费计算
}
}
//获取商品价格
public class ProductPrice {
int getPrice(String product){
return Math.abs(product.hashCode());//模拟获取商品价格
}
}
import java.util.Random;
//库存子系统
public class Stock {
boolean hasStock(String product){
return new Random().nextInt(Math.abs(product.hashCode()))>0;//模拟是否还有库存
}
}
//外观
public class ProductSalesman {
instance;
Stock stock = new Stock();
FinalPrice finalPrice = new FinalPrice();
Object buySomething(String product,String addr,String discountCode){
if(!stock.hasStock(product))
return "库存不足";
int price = finalPrice.getFinalPrice(product, addr, discountCode);
return "订单信息:" + product + "-" + addr + "-" + discountCode + "-" + price;
}
}
public class TestUse {
public static void main(String args[]){
Object info = ProductSalesman.instance.buySomething("银河飞船", "地球", "K1234523");
System.out.println(info);
}
}
动机(Motivation)
模式定义
要点总结
代理模式是我们非常熟悉的一种模式,代码实现也非常简单。被代理对象和代理对象采用同一个接口。
//抽象对象
public interface AbstractObject {
void method1();
int method2();
void method3();
}
//具体对象
public class TargetObject implements AbstractObject {
@Override
public void method1() {
System.out.println("具体对象的方法1");
}
@Override
public int method2() {
System.out.println("具体对象的方法2");
return 0;
}
@Override
public void method3() {
System.out.println("具体对象的方法3");
}
}
//代理对象
public class ProxyObject implements AbstractObject {
AbstractObject object = new TargetObject();
@Override
public void method1() {
object.method1();
}
@Override
public int method2() {
return object.method2();
}
@Override
public void method3() {
System.out.println("调用目标对象前的操作");
object.method3();
System.out.println("调用目标对象后的操作");
}
}
public class TestUse {
public static void main(String args[]){
AbstractObject obj = new ProxyObject();
obj.method1();
obj.method2();
obj.method3();
}
}
动机(Motivation)
模式定义
要点总结
结构图
Target是一端,Adaptee是一端,他们通过Adapter适配起来。
代码示例
我们希望将原来的Adaptee转换为适配Target接口,这种适配功能的完成可以有两种实现方式:类适配器和对象适配器。但是我们更加推荐使用对象适配器,因为这样会比较灵活一点,我可以给对象适配器传入任何满足接口的类,而类适配器就必须和一个具体的类绑定,实际上类适配器也很少被使用。
//老的接口
interface IAdaptee{
void playMp3(Object src);
}
//目标,也就是用户所希望使用的
interface Target{
void playFlac(Object src);
}
//被适配者
class Adaptee implements IAdaptee{
void playMp3(Object src){
System.out.println("播放MP3:" + src);
}
}
//类适配器
public class ClassAdapter extends Adaptee implements Target {
@Override
public void playFlac(Object src) {
//可能需要对src作处理
playMp3(src);
}
}
//对象适配器
public class ObjectAdapter implements Target{
private IAdaptee adaptee;
public ObjectAdapter(IAdaptee adaptee){
this.adaptee = adaptee;
}
@Override
public void playFlac(Object src) {
//可能需要对src作处理
adaptee.playMp3(src);
}
}
public class TestUse {
public static void main(String args[]){
Adaptee adaptee = new Adaptee();
adaptee.playMp3("mp3");
Target target = new ClassAdapter();
target.playFlac("flac");
target = new ObjectAdapter(new Adaptee());
target.playFlac("flac");
}
}
动机(Motivation)
模式定义
要点总结
结构图
代码示例
在代码中无论是PersistentDB
还是PersistentFile
的void getData(Object data,Midiator midiator);
操作触发后,都会触发另一个的void getData(Object data);
的发生,如果不希望触发另一个的发生可以直接使用void getData(Object data);
如果没有中介者,可能我就需要在类中直接使用另一个对象。
//具体中介者
public class Midiator {
PersistentDB persistentDB;
PersistentFile persistentFile;
public Midiator setPersistentDB(PersistentDB persistentDB) {
this.persistentDB = persistentDB;
return this;
}
public Midiator setPersistentFile(PersistentFile persistentFile) {
this.persistentFile = persistentFile;
return this;
}
public void notifyOther(IPersistent persistent,Object data){
if(persistent instanceof PersistentDB)
persistentFile.getData(data);
if(persistent instanceof PersistentFile)
persistentDB.getData(data);
}
}
//同事(接口)
public interface IPersistent {
void getData(Object data);
void getData(Object data,Midiator midiator);
void saveData();
}
//具体同事
public class PersistentDB implements IPersistent{
private Object data;
@Override
public void getData(Object data, Midiator midiator) {
getData(data);
midiator.notifyOther(this, data);
}
@Override
public void saveData() {
System.out.println(data + " 已保存到数据库");
}
@Override
public void getData(Object data) {
this.data = data;
saveData();
}
}
//具体同事
public class PersistentFile implements IPersistent{
private Object data;
@Override
public void getData(Object data, Midiator midiator) {
getData(data);
midiator.notifyOther(this, data);
}
@Override
public void saveData() {
System.out.println(data + " 已保存到文件");
}
@Override
public void getData(Object data) {
this.data = data;
saveData();
}
}
public class TestUse {
public static void main(String args[]){
Object data = "数据";
PersistentDB persistentDB = new PersistentDB();
PersistentFile persistentFile = new PersistentFile();
Midiator midiator = new Midiator();
midiator.setPersistentDB(persistentDB).setPersistentFile(persistentFile);
persistentDB.getData(data, midiator);
persistentFile.getData(data, midiator);
}
}
动机(Motivation)
模式定义
要点总结
在代码中我们根据需要存储的不同数据的大小来确定使用哪种保存方式,但是对外暴露的保存数据接口(saveDataController.save()
)是一样的。
//抽象状态
public interface ISaveData {
void save(Object data);
}
//具体状态
public enum SaveBigData implements ISaveData{
instance;
@Override
public void save(Object data) {
System.out.println("保存到文件:" + data);
}
}
//具体状态
public enum SaveMiddleData implements ISaveData{
instance;
@Override
public void save(Object data) {
System.out.println("保存到Mysql:" + data);
}
}
//具体状态
public enum SaveSmallData implements ISaveData{
instance;
@Override
public void save(Object data) {
System.out.println("保存到Redis:" + data);
}
}
//环境(Context)
public class SaveDataController {
private ISaveData saveData;
public void save(String data){
//为了演示,此处的大的数据其实也是很小的
if(data.length()<1<<2)
saveData = SaveSmallData.instance;
else if(data.length()<1<<4)
saveData = SaveMiddleData.instance;
else
saveData = SaveBigData.instance;
saveData.save(data);
}
}
public class TestUse {
public static void main(String args[]){
String smallData = "小数据";
String middleData = "介于小数据和大数据之间的数据";
String bigData = "这里就假定这是一个很大很大很大的数据";
SaveDataController saveDataController = new SaveDataController();
saveDataController.save(smallData);
saveDataController.save(middleData);
saveDataController.save(bigData);
}
}
动机(Motivation)
模式定义
要点总结
代码示例
备忘录模式使用三个类 Memento、Originator 和 CareTaker。Memento 包含了要被恢复的对象的状态。Originator 创建并在 Memento 对象中存储状态。Caretaker 对象负责从 Memento 中恢复对象的状态。在这里我们将对象的状态简化为了只有一个字符串来描述。
public class Memento {
private String state;
public Memento(String state){
this.state = state;
}
public String getState(){
return state;
}
}
public class Originator {
private String state;
public void setState(String state){
this.state = state;
}
public String getState(){
return state;
}
public Memento saveStateToMemento(){
return new Memento(state);
}
public void getStateFromMemento(Memento Memento){
state = Memento.getState();
}
}
import java.util.ArrayList;
import java.util.List;
public class CareTaker {
private List<Memento> mementoList = new ArrayList<Memento>();
public void add(Memento state){
mementoList.add(state);
}
public Memento get(int index){
return mementoList.get(index);
}
}
public class MementoPatternDemo {
public static void main(String[] args) {
Originator originator = new Originator();
CareTaker careTaker = new CareTaker();
originator.setState("State #1");
originator.setState("State #2");
careTaker.add(originator.saveStateToMemento());
originator.setState("State #3");
careTaker.add(originator.saveStateToMemento());
originator.setState("State #4");
System.out.println("Current State: " + originator.getState());
originator.getStateFromMemento(careTaker.get(0));
System.out.println("First saved State: " + originator.getState());
originator.getStateFromMemento(careTaker.get(1));
System.out.println("Second saved State: " + originator.getState());
}
}
动机(Motivation)
模式定义
要点总结
代码示例
代码示例是非常典型的目录和文件这种结构和整体的组合关系,文件和目录都实现了Component ,从而方便用户使用,而不必区分具体的类型。
import java.util.Iterator;
import java.util.List;
//抽象组件
public interface Component {
void addFile(Component file);
Component addFolder(Component folder);
void removeFile(Component file);
void removeFolder(Component folder);
List<Component> getFiles();
List<Component> getFolders();
List<Component> getAll();
Iterator<Component> iterator();
void display();
}
import java.util.Iterator;
import java.util.List;
//Leaf节点
public class File implements Component{
private String name;
public File(String name){
this.name = name;
}
@Override
public void addFile(Component file) {}
@Override
public Component addFolder(Component folder) { return null; }
@Override
public void removeFile(Component file) {}
@Override
public void removeFolder(Component folder) {}
@Override
public List<Component> getFiles() { return null; }
@Override
public List<Component> getFolders() { return null; }
@Override
public List<Component> getAll() { return null; }
@Override
public Iterator<Component> iterator() { return null; }
@Override
public void display() {
System.out.println(name);
}
}
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Folder implements Component {
private String name;
private List<Component> files;
private List<Component> folders;
public Folder(String name){
this.name = name;
files = new ArrayList<Component>();
folders = new ArrayList<Component>();
}
@Override
public void addFile(Component file) {
files.add(file);
}
@Override
public Component addFolder(Component folder) {
folders.add(folder);
return this;
}
@Override
public void removeFile(Component file) {
files.remove(file);
}
@Override
public void removeFolder(Component folder) {
folders.remove(folder);
}
@Override
public List<Component> getFiles() {
return files;
}
@Override
public List<Component> getFolders() {
return folders;
}
@Override
public List<Component> getAll() {
List<Component> all = new ArrayList<Component>(folders);
all.addAll(files);
return all;
}
@Override
public Iterator<Component> iterator() {
List<Component> all = new ArrayList<Component>();
add(all,this);
return all.iterator();
}
private void add(List<Component> all,Component component){
if(component==null) return;
all.add(component);
Iterator<Component> iterator = component.getFolders().iterator();
while(iterator.hasNext()){
add(all,iterator.next());
}
all.addAll(component.getFiles());
}
@Override
public void display() {
System.out.println(name);
}
}
import java.util.Iterator;
public class TestUse {
public static void main(String args[]){
Component root = new Folder("root");//根目录
Component folder1 = new Folder("java");
Component folder2 = new Folder("c++");
Component folder3 = new Folder("c#");
Component file1 = new File("info.txt");
root.addFolder(folder1).addFolder(folder2).addFolder(folder3).addFile(file1);//添加一级目录
folder1.addFile(new File("info.java"));
Iterator<Component> iterator = root.iterator();
while(iterator.hasNext()){
Component component = iterator.next();
if(component instanceof Folder)
System.out.print("folder:");
else
System.out.print("file:");
component.display();
}
}
}
动机(Motivation)
模式定义
要点总结
结构图
示例代码
在java的集合中,很多实现了迭代器模式。
动机(Motivation)
模式定义
要点总结
示例代码
代码中Handler1
、Handler2
、Handler3
组成一种职责链,我们将所有处理都给Handler1
如果它无法处理就发送给下一个链中的处理者。在实际应用的时候我们需要写一个缺省的处理方式。
//处理者
public interface IHandler {
int handleRequest(int n);
void setNextHandler(Handler next);
}
//第一个具体处理者,处理小于0的
public class Handler1 implements Handler {
private Handler next;
@Override
public int handleRequest(int n) {
if(n<0) return -n;
else{
if(next==null)
throw new NullPointerException("next 不能为空");
return next.handleRequest(n);
}
}
@Override
public void setNextHandler(Handler next) {
this.next = next;
}
}
//第二个具体处理者,处理>=0但小于10的
public class Handler2 implements Handler {
private Handler next;
@Override
public int handleRequest(int n) {
if(n<10) return n*n;
else{
if(next==null)
throw new NullPointerException("next 不能为空");
return next.handleRequest(n);
}
}
@Override
public void setNextHandler(Handler next) {
this.next = next;
}
}
//第三个具体处理者,处理>=0但小于10的
public class Handler3 implements Handler {
private Handler next;
@Override
public int handleRequest(int n) {
if(n<=Integer.MAX_VALUE) return n;
else{
if(next==null)
throw new NullPointerException("next 不能为空");
return next.handleRequest(n);
}
}
@Override
public void setNextHandler(Handler next) {
this.next = next;
}
}
public class TestUse {
public static void main(String args[]){
Handler h1,h2,h3;
h1 = new Handler1();
h2 = new Handler2();
h3 = new Handler3();
h1.setNextHandler(h2);
h2.setNextHandler(h3);
System.out.println(h1.handleRequest(-1));
System.out.println(h1.handleRequest(5));
System.out.println(h1.handleRequest(9999));
}
}
动机(Motivation)
模式定义
要点总结
代码中我们将行为的实现变为了类,通过不同命令作为中介,行为请求者和这些中介打交道,就可以执行相应的行为,并且行为实现者可以变动。
//命令接口
public interface Command {
void execute(String name) throws Exception;
}
//新建文件命令
public class CommandCreate implements Command {
MakeFile makeFile;
public CommandCreate(MakeFile makeFile) {
this.makeFile = makeFile;
}
@Override
public void execute(String name) throws Exception {
makeFile.createFile(name);
}
}
//删文件命令
public class CommandDelete implements Command{
MakeFile makeFile;
public CommandDelete(MakeFile makeFile) {
this.makeFile = makeFile;
}
@Override
public void execute(String name) throws Exception {
makeFile.deleteFile(name);
}
}
//请求者
public class Client {
Command command;
public Client setCommand(Command command){
this.command = command;
return this;
}
public void executeCommand(String name) throws Exception{
if(command==null)
throw new Exception("命令不能为空!");
command.execute(name);
}
}
import java.io.File;
import java.io.IOException;
//接收者
public class MakeFile {
//新建文件
public void createFile(String name) throws IOException{
File file = new File(name);
file.createNewFile();
}
//删除文件
public boolean deleteFile(String name){
File file = new File(name);
if(file.exists()&&file.isFile()){
file.delete();
return true;
}
return false;
}
}
public class TestUse {
public static void main(String args[]) throws Exception{
//接收者
MakeFile makeFile = new MakeFile();
//命令
CommandCreate create = new CommandCreate(makeFile);
CommandDelete delete = new CommandDelete(makeFile);
//请求者
Client client = new Client();
//执行命令
client.setCommand(create).executeCommand("d://test1.txt");
client.setCommand(create).executeCommand("d://test2.txt");
client.setCommand(delete).executeCommand("d://test2.txt");
}
}
动机(Motivation)
模式定义
要点总结
结构图
示例代码
在代码中原来的代码已经固定下来了,但是固定的代码中public void accept(Visitor visitor)
预示了将来可能有扩展的操作。之后Visitor
接口及其子类实现了方法的扩展,如果要使用这些扩展的代码的话,我们需要调用public void accept(Visitor visitor)
这个方法。不过这里只有一个Visitor
的子类,也就是扩展了一个功能,如果需要扩展其他功能的话,写这个接口的其他子类并替换public void accept(Visitor visitor)
的参数即可。
public void accept(Visitor visitor)
预示了将来可能有扩展的操作。//抽象元素
public interface User {
void accept(Visitor visitor);
}
//普通用户,具体元素
public class UserOrdinary implements User{
String estimation;
public UserOrdinary(String estimation){
this.estimation = estimation;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
String getEstimation(){
return estimation;
}
}
//VIP用户,具体元素
public class UserVIP implements User{
String estimation;
public UserVIP(String estimation){
this.estimation = estimation;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
String getEstimation(){
return estimation;
}
}
visit()
方法//抽象访问者
public interface Visitor {
void visit(UserVIP user);
void visit(UserOrdinary user);
}
//具体访问者
public class APPOwner implements Visitor{
@Override
public void visit(UserVIP user) {
String estimation = user.getEstimation();
if(estimation.length()>5)
System.out.println("记录一条有效反馈:" + estimation);
}
@Override
public void visit(UserOrdinary user) {
String estimation = user.getEstimation();
if(estimation.length()>10)
System.out.println("记录一条有效反馈:" + estimation);
}
}
public class TestUse {
public static void main(String args[]){
Visitor appOwner = new APPOwner();
ArrayList<User> users = new ArrayList<User>();
users.add(new UserOrdinary("普通用户短反馈"));
users.add(new UserOrdinary("这是一个普通用户的比较长的反馈"));
users.add(new UserVIP("VIP用户的短反馈"));
users.add(new UserVIP("VIP用户的比较长的反馈反馈"));
Iterator<User> iterator = users.iterator();
while(iterator.hasNext()){
iterator.next().accept(appOwner);
}
}
}
动机(Motivation)
模式定义
要点总结
这是一种不太常用的设计模式,这里不给出示例代码。
学习设计模式之后并不是一定需要使用设计模式,比如以下的一些情况,不要盲目的追求模式的使用,更多的是在实际的项目中体会。