设计模式(六) Adapter

定义:将一个接口转换成客户希望的另一个接口,适配器模式使得原本不能一起工作的类,可以一起工作。

比如原本的类

struct Employee {
    var name: String;
    var title: String;
}

protocol EmployeeDataSource {
    var employees: [Employee] { get };
    func searchByName(name: String) -> [Employee];
    func searchByTitle(title: String) -> [Employee];
}

class DataSourceBase: EmployeeDataSource {
    var employees = [Employee]();
    
    func searchByName(name: String) -> [Employee] {
        return search(selector: { (e) -> Bool in
            return e.name.range(of: name) != nil;
        });
    }
    
    func searchByTitle(title: String) -> [Employee] {
        return search(){(e) -> Bool in
            return e.title.range(of: 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 Developer"));
        employees.append(Employee(name: "Pepe", title: "Developer"));
    }
}

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(name: text) : source.searchByTitle(title: text);
        }
        return results;
    }
    
}

let search = SearchTool(dataSources: SalesDataSource(),DevelopmentDataSource());
print("--List--");
for e in search.employees {
    print("name: \(e.name)")
}

print("--Search--")
for  e in search.search(text: "VP", type: SearchTool.SearchType.TITLE) {
    print("Name: \(e.name), Title: \(e.title)");
}

新加的不兼容的类

class NewCoStaffMember {
    private var name: String;
    private var role: String;
    init(name: String, role: String) {
        self.name = name;
        self.role = role;
    }
    func getName() -> String {
        return name;
    }
    func getJob() -> String {
        return role;
    }
}

class NewCoDirectory {
    private var staff:[String: NewCoStaffMember];
    init() {
        staff = ["Hans": NewCoStaffMember(name: "Hans", role: "Corp Counsel"),
                 "Greta": NewCoStaffMember(name: "Greta", role: "VP, Legal")];
    }
    func getStaff() -> [String: NewCoStaffMember] {
        return staff;
    }
}

适配器模式 使得可以一起工作

extension NewCoDirectory : EmployeeDataSource {
    var employees: [Employee] {
        return getStaff().values.map{ sv -> Employee in
            return Employee(name: sv.getName(), title: sv.getJob());
        }
    }
    
    func searchByName(name: String) -> [Employee] {
        return createEmployees(filter: { (sv: NewCoStaffMember) -> Bool in
            return sv.getName().range(of: name) != nil;
        })
    }

    func searchByTitle(title: String) -> [Employee] {
        return createEmployees(filter: { (sv: NewCoStaffMember) -> Bool in
            return sv.getJob().range(of: title) != nil;
        })
    }
    
    private func createEmployees(filter filterClosure:((NewCoStaffMember) -> Bool)) -> [Employee] {
       return getStaff().values.filter(filterClosure).map { entry -> Employee in
            return Employee(name: entry.getName(), title: entry.getJob());
        } ;
    }
}

let search = SearchTool(dataSources: SalesDataSource(),DevelopmentDataSource(), NewCoDirectory());
print("--List--");
for e in search.employees {
    print("name: \(e.name)")
}

print("--Search--")
for  e in search.search(text: "VP", type: SearchTool.SearchType.TITLE) {
    print("Name: \(e.name), Title: \(e.title)")
}
  • 这里用extension方式实现的
  • 也可使用其他技术,比如,组合的方式。定义一个新类,包含NewCoDirectory对象。实现EmployeeDataSource协议即可。

你可能感兴趣的:(设计模式(六) Adapter)