85 lines
1.9 KiB
Ruby
85 lines
1.9 KiB
Ruby
|
# The Open/Closed Principle states that classes or methods should be open for
|
|||
|
# extension, but closed for modification. This tells us we should strive for
|
|||
|
# modular designs that make it possible for us to change the behavior of the
|
|||
|
# system without making modifications to the classes themselves. This is
|
|||
|
# generally achieved through the use of patterns such as the strategy pattern.
|
|||
|
|
|||
|
# In the below example we can see that we’ll have to modify our file parser
|
|||
|
# anytime we add a client that reports usage information to us in a different
|
|||
|
# file format. This violates the Open/Closed Principle.
|
|||
|
|
|||
|
class FileParser
|
|||
|
attr_reader :file
|
|||
|
|
|||
|
def initialize(file)
|
|||
|
@file = file
|
|||
|
end
|
|||
|
|
|||
|
def parse
|
|||
|
# If we want add new parser we must to edit this method and in private method
|
|||
|
case file.format
|
|||
|
when :xml
|
|||
|
parse_xml
|
|||
|
when :cvs
|
|||
|
parse_cvs
|
|||
|
# when :json
|
|||
|
# parse_json
|
|||
|
else
|
|||
|
# Implementation
|
|||
|
end
|
|||
|
|
|||
|
end
|
|||
|
|
|||
|
private
|
|||
|
|
|||
|
def parse_xml
|
|||
|
# Implementation
|
|||
|
end
|
|||
|
|
|||
|
def parse_cvs
|
|||
|
# Implementation
|
|||
|
end
|
|||
|
|
|||
|
# New parse method
|
|||
|
# def parse_json
|
|||
|
# # Implementation
|
|||
|
# end
|
|||
|
end
|
|||
|
|
|||
|
# Solution
|
|||
|
|
|||
|
# With this refactor we’ve made it possible to add new parsers without changing any code. Any additional behavior will only require the addition of a new handler. This makes our FileParser reusable and in many cases will keep us in compliance with the Single Responsibility Principle as well by encouraging us to create smaller more focused classes.
|
|||
|
|
|||
|
class FileParser
|
|||
|
attr_reader :parser
|
|||
|
|
|||
|
def initialize(parser)
|
|||
|
@parser = parser
|
|||
|
end
|
|||
|
|
|||
|
def parse(file)
|
|||
|
# Now if we want new parser just write new Class and pass it to method
|
|||
|
Data.new(parser.parse file)
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
class JsonParser
|
|||
|
# We write new class for extension solution.
|
|||
|
def self.parse(file)
|
|||
|
# Implementation
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
class XmlParser
|
|||
|
def self.parse(file)
|
|||
|
# Implementation
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
class CvsParser
|
|||
|
def self.parse(file)
|
|||
|
# Implementation
|
|||
|
end
|
|||
|
end
|
|||
|
|