This pattern allows two objects that provide related functionality to work together even when they have incompatible APIs.
回家之后我用xcode ide整理成swift风格的代码格式
Diagram:
client:
let search = SearchTool(dataSources: SalesDataSource(), DevelopmentDataSource());
println("--List--");
for e in search.employees {
println("Name: \(e.name)");
}
println("--Search--");
for e in search.search("VP", type: SearchTool.SearchType.TITLE) {
println("Name: \(e.name), Title: \(e.title)");
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
pattern:
class SearchTool {
enum SearchType {
case NAME; case TITLE;
}
private let sources:[EmployeeDataSource];
init(dataSources: EmployeeDataSource...) {
self.sources = dataSources;
}
var employees:[Employee] {
var results = [Employee]();
for source in sources {
results += source.employees;
}
return results;
}
func search(text:String, type:SearchType) -> [Employee] {
var results = [Employee]();
for source in sources {
results += type == SearchType.NAME ? source.searchByName(text)
: source.searchByTitle(text);
}
return results;
}
}
///
class DataSourceBase : EmployeeDataSource {
var employees = [Employee]();
func searchByName(name: String) -> [Employee] {
return search({e -> Bool in
return e.name.rangeOfString(name) != nil;
});
}
func searchByTitle(title: String) -> [Employee] {
return search({e -> Bool in
return e.title.rangeOfString(title) != nil;
})
}private func search(selector:(Employee -> Bool)) -> [Employee] {
var results = [Employee]();
for e in employees {
if (selector(e)) {
results.append(e);
}
}
return results;
}
}
class SalesDataSource : DataSourceBase {
override init() {
super.init();
employees.append(Employee(name: "Alice", title: "VP of Sales"));
employees.append(Employee(name: "Bob", title: "Account Exec"));
}
}
class DevelopmentDataSource : DataSourceBase {
override init() {
super.init();
employees.append(Employee(name: "Joe", title: "VP of Development"));
employees.append(Employee(name: "Pepe", title: "Developer"));
}
}
/////////
struct Employee {
var name:String;
var title:String;
}
protocol EmployeeDataSource {
var employees:[Employee] { get };
func searchByName(name:String) -> [Employee];
func searchByTitle(title:String) -> [Employee];
}