我無法幫助它,因此我必須爲此做一些工作。
所以它就是這樣。
你已經有了關於蘋果生產者/消費者的想法,所以這就是我要做的。
創建三個接口,並實現如下:
- 產品 - 無論是蘋果,AppleCider,ApplePie,
- 生產者 - 蘋果樹,ApplePress,ApplePieMaker,AppleLoad,
- 消費者 - ApplePress(消耗蘋果) ,ApplePieMaker(消費蘋果),AppleMonitor,AppleSave。
這個想法是有一個通用的產品,由通用生產者生產和消費的通用消費者。
一旦你有了,你可以創建配置文件,就像你描述它的方式,並解析它來爲每個元素創建一個新的實例。
element1 | element2 | element3 <parameters> | element 4
在映射中,創建元素名稱並將其映射到將創建新實例的類。
比方說
map.put("AppleTree", YouAppleTreeClass.class);
所以每次讀取配置的元素時,你創建實例:
for(String item: line) {
Object o = map.get(item).newInstance();
}
最後你要確認您的配置的結構,但基本上能是這樣的:
- 第一個元素應該是生產者
- 最後應該是消費者
- 任何中間應該是生產者 - 消費者
- 您可以分析需要(文件保存爲實例數據)一旦你創建和鏈接所有對象
參數,你開始製作。
有一些事情你必須鍛鍊,但他們很容易:
- 參數傳遞(在那裏他們將被保存在文件/從加載)
- 對象重複使用在不同的配置(總是使用相同的蘋果樹)
最後說明:下面的代碼,只是一個從頭開始,你可能真的考慮依賴注入來完成這項工作,當然它會帶你一點時間去學習它。
配置解析應該手動完成,因爲您使用的格式對最終用戶來說是唯一的,而且應該非常簡單。儘管如此,你仍然可以在你的jar中提供儘可能多的複雜性(使用你需要的任意數量的框架)。
你也可以看看下面的設計模式:
下實施,是一種怪物的這三個(我沒有編譯它,只是拋出一些代碼來展示這個想法會是怎樣的)
我希望這有助於。
/**
* Anything. An apple, cider, pie, whatever.
*/
interface Product{}
// The kinds of products.
class Apple implements Product{}
class ApplePies implements Product{}
class AppleCider implements Product{}
/**
* This indicates the class will do something.
**/
interface Producer {
// adds a consumer to the list.
public void addConsumer(Consumer c);
// removes the consumer from the list.
public void removeConsumer(Consumer c);
// let know eveytone a product has been created.
public void notifyProductCreation(Product someProduct);
// You're producer? Produce then...
public void startProduction();
}
// To avoid copy/paste all around
class AbstractProducer implements Producer {
private List<Consumer> consumers = new ArrayList<Consumer>();
// adds a consumer to the list.
public void addConsumer(Consumer c) {
consumers.add(c);
}
// removes the consumer from the list.
public void removeConsumer(Consumer c) {
consumers.remove(c);
}
public void notifyProductCreation(Product someProduct) {
for(Consumer c : list) {
c.productCreated(someProduct);
}
}
}
interface Consumer {
// Callback to know a product was created
public void productCreated(Product p);
}
class AppleTree extends AbstractProducer {
public void startProduction() {
// do something with earh, sun, water..
// and from time to time:
Product ofThisNewApple = new Apple();
notifyProductCreation(ofThisNewApple);
}
}
class ApplePieMaker extends AbstractProducer implements Consumer {
// Ok, a product was created, but
// is it the product I care?
// check first and consume after.
public void productCreated(Product p){
// Is this the kind of product I can handle..
// well do handle
if(p instanceof Apple) {
/// start producing pies..
}
}
public void startProduction() {
// collect the needed number of apples and then...
Product ofPie = new ApplePie();
notifyProductCreation(ofPie);
}
}
class ApplePress extends AbstractProducer implements Consumer {
// Yeap, something gots produced.
// Just handle if it is an apple
public void productCreated(Product p) {
if(p instanceof Apple) {
// start producing cider
}
}
public void startProduction() {
// collect the needed number of apples and then...
Product ofCiderBottle = new AppleCider();
notifyProductCreation(ofCiderBottle);
}
}
class AppleSave implements Consumer {
public void productCreated(Product p) {
file.append(p);// any one will do.
}
}
class AppleLoad extends AbstractProducer {
public void startProduction() {
readFromFile();
}
private readFromFile() {
for(Product p : file) {
notifyProductCreation(p);
}
}
}
class Main {
public static void main(String [] args) {
Configuration conf = new Configuration();
List<Producer> producers conf.read();
for(Producer p : producers) {
// fasten your seat belts....
p.startProduction();
}
}
}
/// Ahhh, pretty ugly code below this line.
// the idea is:
// Read the configuration file
// for each line split in the "|"
// for each element create a new instance
// and chain it with the next.
// producer | consumer | etc...
// Becomes....
// new Producer().addConsumer(new Consumer());
// Return the list of create producers.
class Configuration {
List<Producer> producers
// read the file
// create the instances
// let them run.
public List<Producer> read() {
File file = new File(....
// The format is:
// producer | consumer-producer <params> | consumer
String line = uniqueLineFrom(file);
String [] parts = line.split("|");
if(parts.length == 1) {
System.err.println("Invalid configuration. use element | element | etc. Only one element was....");
System.exit(1);
}
int length = parts.length;
for(int i = 0 ; i < parts.length ; i++) {
Object theInstance = implementationMap.get(parts[i]).newInstance();
validatePosition(i, length, theInstance , parts[i]);
}
List<Producer> producers = new ArrayList<Producer>();
for(int i = 0 ; i < parts.length ; i++) {
Object theInstance = getInstance(parts[i]);
if(not(isLast(i, length) && isProducer(theInstance)) {
// the next is its consumer
Producer producer = (Producer) theInstance;
producer.addConsumer((Consumer) getInstance(parts[i+1]));
producers.add(producer);
}
}
return producers;
}
// creates a new instance from the implementation map.
private Object getInstance(String key) {
return implementationMap.get(part[i]).newInstance();
}
// validates if an element at the given position is valid or not.
// if not, prints the message and exit.
// the first element most be a producer
// the last one a consumer
// all the middle elements producer-consumer
//
private void validatePosition(int i, int length, Object theInstance, String element ) {
if(isFirst(i) && not(isProducer((theInstance)))) {
System.err.println("Invalid configuration: " + element + " most be a producer (either Ap...");
System.exit(2);
} else if (isLast(i, length) && not(isConsumer(theInstance ))) {
System.err.println("Invalid configuration: " + element + " most be a consumer (either Ap...");
System.exit(3);
} else if (isMiddleAndInvalid(i, length , instance)) {
System.err.println("Invalid configuration: " + element + " most be a producer-consumer (either Ap...");
System.exit(4);
}
}
private static Map<String,Class> implementationMap = new HashMap<String,Class>() static {
implementationMap.put("AppleTree", AppleTree.class);
implementationMap.put("ApplePieMaker ", ApplePieMaker .class);
implementationMap.put("ApplePress", ApplePress.class);
implementationMap.put("AppleSave", AppleSave.class);
implementationMap.put("AppleLoad", AppleLoad.class);
implementationMap.put("ApplePieMonitor", ApplePieMonitor.class);
};
// Utility methods to read better (hopefully) the statements
// If you could read the validations above you may ignore these functions.
private boolean not(boolean value) {
return !value;
}
private boolean isFirst(int i ) {
return i == 0;
}
private boolean isLast(int i, int l) {
return i == l -1 ;
}
private boolean isProducer(Object o) {
return o instanceof Producer;
}
private boolean isConsumer(Object o) {
return o instanceof Consumer;
}
private boolean isMiddleAndInvalid(int index, int length, Object instance) {
return not(isFirst(index)) && not(isLast(index, length)) && not(isProducer(instance) && isConsumer(instance));
}
}
如何配置流量?通過GUI或通過文本文件?或者一個網頁。我問的是,最終用戶如何配置流量? – OscarRyz 2009-02-18 21:29:09
什麼是用戶使用和我實現的最簡單的組合。所以可能通過一個非常簡單的文本或XML文件。 – 2009-02-19 13:58:03