
-- Adaptee
local StringList = {}
StringList.__index = StringList
function StringList.new()
return setmetatable({rows = {}}, StringList)
end
function StringList:add(value)
self.rows[#self.rows + 1] = value
end
-- SpecificRequest()
function StringList:get_string()
return table.concat(self.rows, "\n")
end
-- Adapter: keeps the adaptee in a field;
-- no method of the adaptee is inherited
local TextAdapter = {}
TextAdapter.__index = TextAdapter
function TextAdapter.new()
local adapter = {string_list = StringList.new()}
return setmetatable(adapter, TextAdapter)
end
-- Request()
function TextAdapter:get_text()
return self.string_list:get_string()
end
-- Client
local adapter = TextAdapter.new()
adapter.string_list:add("line 1")
adapter.string_list:add("line 2")
local text = adapter:get_text()
-- text = line 1
-- line 2
print("text = " .. text)
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.Read moreThe problem. Your program reads text from any source through one method. Another part of the system gives you ready lists of lines. A list can join its lines, but through a method with another name. The lists arrive already filled, and you cannot change their class. You also do not want to change the code that calls the method it expects. The idea. An adapter makes an existing class, the adaptee, fit the interface that the client expects, the target. In this version the adapter implements the target and holds a reference to an adaptee object. Its target method forwards the call to that object, sometimes with a small conversion. The adapter does not have the other methods of the adaptee. Compare the adapter by inheritance: it extends the adaptee instead of holding it. How to read the example. There are two objects: the adaptee and the adapter that holds it. In most languages the adaptee is created separately and given to the adapter. In a few, the adapter creates its own adaptee, and the client fills it through the adapter's field. The client reads the result only through the target method, and the adapter forwards this call to the adaptee. Some adapters return an empty result when they hold no adaptee. In some languages the adapter is simply a function that captures the adaptee. When to use it. Prefer an object adapter in most cases. It can adapt any object of the adaptee type, including subclasses and objects that already exist. Do not use an adapter at all when you can simply change the adaptee: renaming one method is cheaper. A common mistake. Putting new logic into the adapter. An adapter only translates one call into another. Checks and business rules belong elsewhere. |